home *** CD-ROM | disk | FTP | other *** search
Text File | 1995-11-14 | 153.5 KB | 5,332 lines |
- diff -u -r --new-file last-version/docs/BROWSING.txt samba-1.9.15/docs/BROWSING.txt
- --- last-version/docs/BROWSING.txt Tue Jan 10 22:05:51 1995
- +++ samba-1.9.15/docs/BROWSING.txt Tue Nov 14 22:29:10 1995
- @@ -1,18 +1,17 @@
- BROWSING
- ========
-
- -Samba has recently begun support for browsing. The browsing is
- -supported by nmbd and is also controlled by options in the smb.conf
- -file (see smb.conf(5)).
- -
- -Samba does not act as a browse master for a workgroup, so it can only
- -participate in workgroups which already have a browse master. If you
- -have any WfWg or WinNT machines in your workgroup that exports a share
- -then you already have a browse master so this shouldn't be a problem.
- -
- -To get browsing to work you need to run nmbd as usual, but need to
- -either give the -G option to elect which workgroup Samba will be part
- -of, or use a lmhosts file.
- +Samba now fully supports browsing. The browsing is supported by nmbd
- +and is also controlled by options in the smb.conf file (see
- +smb.conf(5)).
- +
- +Samba can act as a browse master for a workgroup, but currently cannot
- +act as a domain controller. The ability to be a domain controller will
- +be added in a later version.
- +
- +To get browsing to work you need to run nmbd as usual, but will need
- +to use the "workgroup" option in smb.conf to control what workgroup
- +Samba becomes a part of.
-
- The -G option is most useful for simple setups where Samba is browsable
- in only one workgroup. In more complex cases the lmhosts file is
- @@ -33,7 +32,12 @@
- # our own net address
- 0.0.0.0 MYGROUP G
-
- -Samba has a useful option for a Samba server to offer itself for
- +Note in the above that I overrode what workgroup Samba is in using the
- +G flag. Also note that the 0.0.0.0 address is used, which will be
- +automatically replaced with the broadcast address for groups, and with
- +the local IP address for other entries.
- +
- +Samba also has a useful option for a Samba server to offer itself for
- browsing on another subnet.
-
- This works by the lmhosts file specifying a broadcast address on the
- @@ -44,25 +48,19 @@
- do the trick:
-
- # put ourselves in the STAFF workgroup on the other subnet
- -192.0.3.255 STAFF S
- -
- -Notice the S at the end! It is very important you include this as this
- -entry without the S could cause a broadcast storm!
- +192.0.3.255 STAFF G
-
- -If browsing is causing you trouble you can disable it with the -b
- -option to nmbd.
- +Notice the G at the end! It is very important you include this as this
- +entry without the G could cause a broadcast storm!
-
- -If something doesn't work then hopefully the log.nmb.debug file will
- -help you track down the problem.
- +If something doesn't work then hopefully the log.nmb file will
- +help you track down the problem. Try a debug level of 2 or 3 for
- +finding problems.
-
- Note that if it doesn't work for you, then you should still be able to
- type the server name as \\SERVER in filemanager then hit enter and
- filemanager should display the list of available shares.
-
- -Remember: Samba can only participate in EXISTING workgroups. If you specify
- -a workgroup that dosn't exist then browsing won't work. In future versions
- -Samba will probably be able to create it's own workgroups.
- -
- Some people find browsing fails because they don't have the global
- "guest account" set to a valid account. Remember that the IPC$
- connection that lists the shares is done as guest, and thus you must
- @@ -75,36 +73,34 @@
- are now far more likely to correctly find your broadcast and network
- addess, so in most cases these aren't needed.
-
- -
- -FINDING A MASTER BROWSER
- -========================
- -
- -Often people find that nmbd has trouble finding a master browser. The
- -likely causes of this problem are:
- +The other big problem people have is that their broadcast address,
- +netmask or IP address is wrong (specified with the -B, -N and -I
- +options to nmbd).
-
- -1) you are using the wrong broadcast address
- -
- -2) You are using the wrong workgroup name
- -
- -3) You don't have a master browser.
- -
- -To find out which of the above problems applies to you use the -M
- -switch to nmbd to search for a master browser manually. eg:
- +FORCING SAMBA TO BE THE MASTER
- +==============================
-
- -nmbd -M FOOGROUP -B a.b.c.d
- +Who becomes the "master browser" is determined by an election process
- +using broadcasts. Each election packet contains a number of parameters
- +which determine what precedence (bias) a host should have in the
- +election. By default Samba uses a very low precedence and thus loses
- +elections to just about anyone else.
- +
- +If you want Samba to win elections then just set the "os level" global
- +option in smb.conf to a higher number. It defaults to 0. Using 3 would
- +make it win all elections over every other system (except other samba
- +systems!)
-
- -This will look for a master browser for the workgroup FOOGROUP using
- -broadcast a.b.c.d. When you successfully find a master browser you
- -know you have the broadcast and group name right.
- +A "os level" of 2 would make it beat WfWg and Win95, but not NTAS.
-
-
- NOTE ABOUT BROADCAST ADDRESSES
- ==============================
-
- If your network uses a "0" based broadcast address (for example if it
- -ends in a 0) then you may strike problems. Windows for Workgroups does
- -not seem to support a 0's broadcast and you will probably find that
- -browsing and name lookups won't work.
- +ends in a 0) then you will strike problems. Windows for Workgroups
- +does not seem to support a 0's broadcast and you will probably find
- +that browsing and name lookups won't work.
-
- You have a few options:
-
- @@ -112,7 +108,9 @@
- .255 (check with your local network guru for details)
-
- 2) set the nmbd broadcast to a 1's based address on the command line using
- -the -B option.
- +the -B option. This only works if your network setup listens on both
- +0s and 1s based broadcasts. The -B option can only control what
- +address it sends to, not what it listens on.
- +
-
- -3) explicitly support both broadcasts with two entries in your lmhosts file.
-
- diff -u -r --new-file last-version/docs/DIAGNOSIS.txt samba-1.9.15/docs/DIAGNOSIS.txt
- --- last-version/docs/DIAGNOSIS.txt Sat Nov 11 14:19:09 1995
- +++ samba-1.9.15/docs/DIAGNOSIS.txt Tue Nov 14 22:41:04 1995
- @@ -36,8 +36,8 @@
- read only = yes
-
-
- -These tests also assume version 1.9.14 or later of the samba suite. If
- -you have version 1.9.13 then see "NOTE 1" below.
- +THESE TESTS ASSUME VERSION 1.9.15 OR LATER OF THE SAMBA SUITE. SOME
- +COMMANDS SHOWN DID NOT EXIST IN EARLIER VERSIONS
-
-
- TEST 1:
- @@ -91,11 +91,8 @@
- TEST 4:
- -------
-
- -run the command "nmbd -L __SAMBA__ -B BIGSERVER". You should get a
- -bunch of info back including the string "got a positive name query
- -response". You should also see a message "got a positive node status
- -response" and below that a list of netbios names. The name BIGSERVER
- -should be included in that list.
- +run the command "nmblookup -B BIGSERVER __SAMBA__". You should get the
- +IP address of your Samba server back.
-
- If you don't then nmbd is incorrectly installed. Check your inetd.conf
- if yu run it from there, or that the daemon is running and listening
- @@ -109,40 +106,41 @@
- TEST 5:
- -------
-
- -run the command "nmbd -L '*' -B ACLIENT"
- +run the command "nmblookup -B ACLIENT '*'"
-
- -You should get a "positive name query response" from the PC. If you
- -don't then the client software on the PC isn't installed correctly, or
- -isn't started, or you got the name of the PC wrong. Note that you
- -probably won't get a "node status response" from the PC due to a bug
- -in the microsoft netbios nameserver implementation (it responds to the
- -wrong port number).
- +You should get the PCs IP address back. If you don't then the client
- +software on the PC isn't installed correctly, or isn't started, or you
- +got the name of the PC wrong. Note that you probably won't get a "node
- +status response" from the PC due to a bug in the microsoft netbios
- +nameserver implementation (it responds to the wrong port number).
-
- TEST 6:
- -------
-
- -run the command "nmbd -L '*'"
- +run the command "nmblookup -d 2 '*'"
-
- This time we are trying the same as the previous test but are trying
- -it via a broadcast to the default broadcast address. All Netbios/TCPIP
- -hosts on the network should respond, although Samba may not catch all
- -of the responses in the short time it listens.
- -
- -If this doesn't give a similar result to the previous test then nmbd
- -isn't correctly getting your broadcast address through its automatic
- -mechanism. In this case you should experiment with the -B option which
- -allows you to manually specify the broadcast address, overriding the
- -automatic detection. You should try different broadcast addresses
- -until your find the one that works. It will most likely be something
- -like a.b.c.255 as microsoft tcpip stacks only listen on 1's based
- -broadcast addresses. If you get stuck then ask your local networking
- -guru for help (and show them this paragraph).
- +it via a broadcast to the default broadcast address. A number of
- +Netbios/TCPIP hosts on the network should respond, although Samba may
- +not catch all of the responses in the short time it listens. You
- +should see "got a positive name query response" messages from several
- +hosts.
- +
- +If this doesn't give a similar result to the previous test then
- +nmblookup isn't correctly getting your broadcast address through its
- +automatic mechanism. In this case you should experiment with the -B
- +option which allows you to manually specify the broadcast address,
- +overriding the automatic detection. You should try different broadcast
- +addresses until your find the one that works. It will most likely be
- +something like a.b.c.255 as microsoft tcpip stacks only listen on 1's
- +based broadcast addresses. If you get stuck then ask your local
- +networking guru for help (and show them this paragraph).
-
- If you find you do need the -B option (ie. the automatic detection
- doesn't work) then you should add the -B option with the right
- broadcast address for your network to the command line of nmbd in
- inetd.conf or in the script you use to start nmbd as a daemon. Once
- -you do this go back to the "nmbd -L __SAMBA__ -B BIGSERVER" test to
- +you do this go back to the "nmblookup __SAMBA__ -B BIGSERVER" test to
- make sure you have it running properly.
-
- If your PC and server aren't on the same subnet then you will need to
- @@ -152,16 +150,6 @@
- TEST 7:
- -------
-
- -run the command "nmbd -M -"
- -
- -this should find a master browser on your network. If you don't have
- -one then browsing won't work with samba. See the file BROWSING.txt for
- -details. Note that you may need the -B option to the command if the
- -previous test showed that the default broadcast is incorrect.
- -
- -TEST 8:
- --------
- -
- run the command "smbclient '\\BIGSERVER\TMP'". You should then be
- prompted for a password. You should use the password of the account
- you are logged into the unix box with. If you want to test with
- @@ -187,7 +175,7 @@
- when you type "dir".
-
-
- -TEST 9:
- +TEST 8:
- -------
-
- On the PC type the command "net view \\BIGSERVER". You will need to do
- @@ -212,7 +200,7 @@
- pages)
-
-
- -TEST 10:
- +TEST 9:
- --------
-
- run the command "net use x: \\BIGSERVER\TMP". You should be prompted
- @@ -228,7 +216,7 @@
- fixes things you may need the username mapping option.
-
-
- -TEST 11:
- +TEST 10:
- --------
-
- From file manager try to browse the server. Your samba server should
- @@ -246,18 +234,4 @@
- Try the mailing list or newsgroup, or use the tcpdump-smb utility to
- sniff the problem.
-
- -
- -ADDITIONAL NOTES
- -----------------
- -
- -NOTE 1:
- -
- -If you have version 1.9.13 of Samba then the "nmbd -L ACLIENT -B
- -ACLIENT" test may fail if your client doesn't export any shares. To
- -fix this either export a share or change the "lookup_type" in
- -nameserv.c from ' ' to 0 and recompile.
- -
- -Also the "wildcard" lookup capability used in the command "nmbd -L
- -'*'" was only added in 1.9.14. If you have 1.9.13 then use a clients
- -netbios name instead (for example "nmbd -L ACLIENT").
-
- diff -u -r --new-file last-version/docs/HINTS.txt samba-1.9.15/docs/HINTS.txt
- --- last-version/docs/HINTS.txt Wed Apr 26 16:36:44 1995
- +++ samba-1.9.15/docs/HINTS.txt Tue Nov 14 22:41:54 1995
- @@ -124,19 +124,6 @@
-
- Often WfWg will totally ignore a password you give it in a dialog box.
-
- -
- ------------------------
- -HINT: Getting WfWg to be a master browser
- -
- -Apart from exporting a drive, you should be able to get WfWg to be a
- -master browser by using:
- -
- -[Network]
- -MaintainServerList=YES
- -
- -in the system.ini file
- -
- -
- ----------------------
- HINT: Using MS Access
-
- diff -u -r --new-file last-version/docs/INSTALL.txt samba-1.9.15/docs/INSTALL.txt
- --- last-version/docs/INSTALL.txt Fri Jul 7 08:30:27 1995
- +++ samba-1.9.15/docs/INSTALL.txt Tue Nov 14 22:55:40 1995
- @@ -50,11 +50,14 @@
- The simplest useful configuration file would be something like this:
-
- [homes]
- + workgroup = MYGROUP
- guest ok = no
- read only = no
-
- which would allow connections by anyone with an account on the server,
- -using either their login name or "homes" as the service name.
- +using either their login name or "homes" as the service name. (Note
- +that I also set the workgroup that Samba is part of. See BROWSING.txt
- +for defails)
-
- Note that "make install" will not install a smb.conf file. You need to
- create it yourself. You will also need to create the path you specify
- @@ -147,7 +150,7 @@
- also be used to see what shares are available on other LanManager
- clients (such as WfWg).
-
- -If you chose user level security then you may find that Samba requests
- +If you choose user level security then you may find that Samba requests
- a password before it will list the shares. See the smbclient docs for
- details. (you can force it to list the shares without a password by
- adding the option -U% to the command line. This will not work with
- @@ -199,72 +202,21 @@
- documentation (or source code) so that the next person will find it
- easier.
-
- +DIAGNOSING PROBLEMS
- +===================
-
- -TESTING NMBD
- -============
- +If you have instalation problems then go to DIAGNOSIS.txt to try to
- +find the problem.
-
- -As of version 1.7.00 it is possible to test nmbd to see if it is
- -correctly installed. This can also test to see if it can auto-detect
- -your broadcast address.
- -
- -Under some operating systems you can only test the broadcast part if
- -running as root. You can test other functionality from a non-root
- -account. To test from root use:
- -
- -nmbd -L TESTNAME
- -
- -where TESTNAME is the netbios name you wish to test. This would
- -typically be the hostname of the unix host where you installed nmbd.
- -It should return the IP address of the host you are looking for. If it
- -doesn't then something is wrong with your nmbd configuration. (It is
- -also possibe that you have a net configuration that doesn't send
- -broadcasts to itself. Some Linux configurations do this.)
- -
- -If it fails then it could mean it is not correctly detecting your
- -broadcast address or netmask. You will then need to supply the -B and
- --N parameters. See the nmbd man page for details.
- -
- -It has succeeded if somewhere in the output is a line like:
- -
- -ww.xx.yy.zz HOSTNAME
- -
- -which means it managed to look the IP correctly.
- -
- -To test from a non-root account use:
- -
- -nmbd -B HOSTNAME -L TESTNAME
- -
- -where hostname is the host name of the host where nmbd is installed
- -and TESTNAME is the name you want to test. Typically this would be the
- -same as HOSTNAME.
- -
- -
- -NAME RESOLUTION
- -===============
- -
- -Probably the most common problem people have when installing Samba is
- -getting name resolution to work. This is usually caused by incorrect
- -settings for nmbd.
- -
- -One solution is to use nmbd as a WINS server, instead of using name
- -resolution by broadcast. To do this you need to enter the IP address
- -of the Samba server in the WINS section of your WfWg, Win95 or WinNT TCP/IP
- -setup.
- -
- -As a last resort you can use a lmhosts file on the PC to resolve names,
- -as long as you enable lmhosts name resolution in the right dialog
- -box. This doesn't lend itself very well to update, however.
- -
- -The best solution is, however, to fix the nmbd setup. Experimentation
- -and careful reading of the Samba docs should help.
- -
- SCOPE IDs
- =========
-
- By default Samba uses a blank scope ID. This means all your windows
- boxes must also have a blank scope ID. If you really want to use a
- non-blank scope ID then you will need to use the -i <scope> option to
- -nmbd, smbd, and smbclient.
- +nmbd, smbd, and smbclient. All your PCs will need to have the same
- +setting for this to work. I do not recommend scope IDs.
- +
-
- CHOOSING THE PROTOCOL LEVEL
- ===========================
- @@ -350,9 +302,9 @@
- DENY_NONE, DENY_READ, DENY_WRITE or DENY_ALL. There are also special
- compatability modes called DENY_FCB and DENY_DOS.
-
- -By default Samba does not implement these share modes. If you use
- -"share modes = yes" then Samba will implement them using locking files
- -in the "lock directory". See the man pages for details.
- +You can disable share modes using "share modes = no". This may be
- +useful on a heavily loaded server as the share modes code is very
- +slow.
-
-
- MAPPING USERNAMES
- diff -u -r --new-file last-version/docs/MIRRORS samba-1.9.15/docs/MIRRORS
- --- last-version/docs/MIRRORS Fri Sep 15 19:02:39 1995
- +++ samba-1.9.15/docs/MIRRORS Mon Nov 13 08:31:20 1995
- @@ -8,7 +8,7 @@
- ftp://sunsite.unc.edu/pub/Linux/system/Network/Samba/
- ftp://ftp.choc.apana.org.au/pub/samba
- ftp://ftp.uni-trier.de/pub/unix/network/samba/
- -
- +ftp://ftp.spectrum.titan.com/pub/samba
-
- There are several others. Give archie a try.
-
- diff -u -r --new-file last-version/docs/nmbd.8 samba-1.9.15/docs/nmbd.8
- --- last-version/docs/nmbd.8 Mon Apr 17 18:27:52 1995
- +++ samba-1.9.15/docs/nmbd.8 Tue Nov 14 22:33:04 1995
- @@ -20,23 +20,9 @@
- .B -H
- .I netbios hosts file
- ] [
- -.B -L
- -.I netbios name
- -] [
- -.B -M
- -.I workgroup name
- -] [
- .B -N
- .I netmask
- ] [
- -.B -P
- -] [
- -.B -R
- -] [
- -.B -b
- -] [
- -.B -S
- -] [
- .B -d
- .I debuglevel
- ] [
- @@ -46,22 +32,17 @@
- .B -n
- .I netbios name
- ] [
- -.B -O
- -.I socket options
- -] [
- .B -p
- .I port number
- -] [
- -.B -T
- -.I browse interval
- ]
- +
- .SH DESCRIPTION
- This program is part of the Samba suite.
-
- .B nmbd
- is a server that understands and can reply to netbios
- name service requests, like those produced by LanManager
- -clients.
- +clients. It also controls browsing.
-
- LanManager clients, when they start up, may wish to locate a LanManager server.
- That is, they wish to know what IP number a specified host is using.
- @@ -82,11 +63,6 @@
- means is that it will respond to all name requests that it receives
- that are not broadcasts, as long as it can resolve the name.
- .SH OPTIONS
- -.B -b
- -
- -.RS 3
- -This toggles support for browsing from WfWg. It defaults to on.
- -.RE
- .B -B
-
- .RS 3
- @@ -172,7 +148,7 @@
- from the -G option) are registered on the network (unless the -R
- option has been selected).
-
- -A S means that the specified address is a broadcast address of a
- +A S or G means that the specified address is a broadcast address of a
- network that you want people to be able to browse you from. Nmbd will
- search for a master browser in that domain and will send host
- announcements to that machine, informing it that the specifed somain
- @@ -209,7 +185,7 @@
-
- # now we want another subnet to be able to browse
- # us in the workgroup UNIXSERV
- - 192.0.2.255 UNIXSERV S
- + 192.0.2.255 UNIXSERV G
-
- .RE
-
- @@ -229,33 +205,6 @@
- as a daemon or in inetd.
-
- .RE
- -.B -L
- -.I netbios name
- -
- -.RS 3
- -If this parameter is given, the server will look up the specified
- -.I netbios name,
- -report success or failure, then exit. If successful, the IP address of the
- -name located will be reported. This is useful for determining whether
- -a netbios name is in use on a subnet and for matching IP addresses to netbios
- -names.
- -
- -This option is meant to be used interactively on the command line, not
- -as a daemon or in inetd.
- -
- -Use of this parameter causes options
- -.B -D
- -,
- -.B -P
- -,
- -.B -R
- -and
- -.B -n
- -to be ignored.
- -
- -By default, the server will NOT do this.
- -.RE
- -
- .B -N
-
- .RS 3
- @@ -272,28 +221,6 @@
- number.
- .RE
-
- -.B -P
- -
- -.RS 3
- -If specified, this parameter causes the server to operate passively. That is,
- -it continues to field requests, but will not respond.
- -
- -By default, the server will NOT operate passively.
- -.RE
- -
- -.B -S
- -
- -.RS 3
- -If specified, this parameter causes the server to respond to broadcast
- -name queries for hosts that can be found with the gethostbyname() call
- -(which normally goes to NIS or DNS). It will NOT respond if the host
- -being queried is on the same subnet as the server. This is useful so
- -clients can connect to servers to which they cannot broadcast.
- -
- -By default, the server will NOT respond to any broadcast queries other
- -than it's own name.
- -.RE
- -
- .B -d
- .I debuglevel
- .RS 3
- @@ -351,13 +278,6 @@
- name of the host on which the server is running.
- .RE
-
- -.B -O
- -.I socket options
- -.RS 3
- -
- -See the socket options section of smb.conf(5) for details
- -
- -.RE
- .B -p
- .I port number
- .RS 3
- @@ -377,13 +297,6 @@
-
- This parameter is not normally specified except in the above situation.
- .RE
- -.B -T
- -.I browse interval
- -.RS 3
- -
- -This sets the number of seconds between browse announcements. It
- -defaults to 60 seconds. The minimum value is 10 seconds.
- -
- .SH FILES
-
- .B /etc/inetd.conf
- diff -u -r --new-file last-version/docs/smb.conf.5 samba-1.9.15/docs/smb.conf.5
- --- last-version/docs/smb.conf.5 Sun Nov 5 11:35:38 1995
- +++ samba-1.9.15/docs/smb.conf.5 Tue Nov 14 22:47:42 1995
- @@ -366,6 +366,8 @@
-
- null passwords
-
- +os level
- +
- packet size
-
- passwd chat
- @@ -376,6 +378,8 @@
-
- password server
-
- +preferred master
- +
- preload
-
- printing
- @@ -1492,6 +1496,10 @@
- .B Example:
- null passwords = yes
-
- +.SS os level (G)
- +This integer value controls what level Samba advertises itself as for
- +browse elections. See BROWSING.txt for details.
- +
- .SS packet size (G)
- The maximum transmit packet size during a raw read. This option is no
- longer implemented as of version 1.7.00, and is kept only so old
- @@ -1693,6 +1701,13 @@
- .B Example:
- preexec = echo \"%u connected to %S from %m (%I)\" >> /tmp/log
-
- +.SS preferred master (G)
- +This boolean parameter controls if Samba is a preferred master browser
- +for its workgroup. Setting this gives it a slight edge in elections
- +and also means it will automatically start an election when it starts
- +up.
- +
- +It is on by default.
-
- .SS preload
- This is an alias for "auto services"
- diff -u -r --new-file last-version/source/Makefile samba-1.9.15/source/Makefile
- --- last-version/source/Makefile Sun Nov 12 12:56:19 1995
- +++ samba-1.9.15/source/Makefile Tue Nov 14 21:28:52 1995
- @@ -425,7 +425,7 @@
- LIBS = $(LIBS1) $(LIBSM) $(DCE_LIBS) $(DES_LIB)
-
- PROGS1 = smbd smbclient nmbd testparm testprns smbrun smbstatus smbpasswd
- -PROGS = $(PROGS1) nmbd2 nmblookup
- +PROGS = $(PROGS1) nmblookup
- SCRIPTS = smbtar
-
- all : CHECK $(PROGS)
- @@ -462,17 +462,13 @@
- @echo Linking smbrun
- @$(CC) $(CFLAGS) -o smbrun smbrun.o $(LIBS)
-
- -nmbd: nameserv.o $(UTILOBJ)
- - @echo Linking nmbd
- - @$(CC) $(CFLAGS) -o nmbd nameserv.o $(UTILOBJ) $(LIBS)
- -
- nmblookup: nmblookup.o $(UTILOBJ)
- @echo Linking nmblookup
- @$(CC) $(CFLAGS) -o nmblookup nmblookup.o nmblib.o $(UTILOBJ) $(LIBS)
-
- -nmbd2: nameserv2.o nmblib.o $(UTILOBJ)
- - @echo Linking nmbd2
- - @$(CC) $(CFLAGS) -o nmbd2 nameserv2.o nmblib.o $(PARAMOBJ) $(LIBS)
- +nmbd: nameserv.o nmblib.o $(UTILOBJ)
- + @echo Linking nmbd
- + @$(CC) $(CFLAGS) -o nmbd nameserv.o nmblib.o $(PARAMOBJ) $(LIBS)
-
- smbclient: client.o clitar.o getsmbpass.o $(UTILOBJ)
- @echo Linking smbclient
- diff -u -r --new-file last-version/source/change-log samba-1.9.15/source/change-log
- --- last-version/source/change-log Sun Nov 12 21:41:40 1995
- +++ samba-1.9.15/source/change-log Tue Nov 14 23:17:02 1995
- @@ -1591,7 +1591,7 @@
- - added force_user to conn struct
-
-
- -2.0.0:
- +1.9.15: 14/11/95
- - removed bcast override from workgroup announce in nmbd
- - aix patch, added NO_SYSMOUNTH, from
- lionel leston <102624.346@compuserve.com>
- @@ -1645,11 +1645,30 @@
- - added browse mastering code
- - started integration with smb.conf for nmbd2
- - released p5
- + - fixed death_time (should be t+ttl*3)
- + - fixed non-removal of dead servers
- + - added smbstatus -u patch from oskarh@spornet.is (Oskar Hannesson)
- + - NETGROUP fix from J.W.Schilperoort@research.kpn.com
- + - select and NO_SETGROUPS patches from lennylim@netcom.com (Lenny
- + Lim)
- + - added LINKS_READ_ONLY define in dos_mode() for LM/X
- + compatability
- + - "dir a.c" bug fixed thanks to roderich@nodebonn.muc.bmw.de
- + (Roderich Schupp)
- + - job cancel fix in client from peo@mtek.chalmers.se
- + - changed nmbd2 to nmbd
- + - fixed "dir a*" under trans2 lookups
- + - added StrnCaseCmp()
- + - updated docs a bit for new browsing stuff
- + - updated INSTALL.txt
- + - hopefully fixed server level security with WfWg
-
-
- ==========
- todo:
-
- +dup/close 0 for getopt?
- +
- implement SMBmove and SMBcopy ??
-
- add option to print more info about locked files (full path, share name
- @@ -1659,8 +1678,6 @@
-
- no refresh/reg of new IP? or send wack and challenge owner?
-
- -new nmb.conf file
- -
- protocol drop back in client to avoid openX etc.
-
- very slow listing CD, perhaps because of order of stat and readdir?
- @@ -1688,4 +1705,10 @@
- ALLOW_PASSWORD_CHANGE only compiles/works on some systems
-
- weird foooooooo/open.exe bug on NT
- +
- +
- +lpd stuff:
- + Tony Aiuto (tony@ics.com)
- +
- +
-
- diff -u -r --new-file last-version/source/client.c samba-1.9.15/source/client.c
- --- last-version/source/client.c Sat Nov 11 15:23:12 1995
- +++ samba-1.9.15/source/client.c Tue Nov 14 21:54:30 1995
- @@ -615,7 +615,7 @@
- {
-
- if (!((finfo->mode & aDIR) == 0 && *fileselection &&
- - !mask_match(finfo->name,fileselection,False,True)) &&
- + !mask_match(finfo->name,fileselection,False,False)) &&
- !(recurse_dir && (strequal(finfo->name,".") ||
- strequal(finfo->name,".."))))
- {
- @@ -2155,7 +2155,7 @@
- p = skip_string(p,1);
- strcpy(p,"");
- p = skip_string(p,1);
- - SSVAL(p,0,0); /* level 0 */
- + SSVAL(p,0,job);
- p += 2;
-
- if (call_api(PTR_DIFF(p,param),0,
- diff -u -r --new-file last-version/source/includes.h samba-1.9.15/source/includes.h
- --- last-version/source/includes.h Sun Nov 12 12:31:47 1995
- +++ samba-1.9.15/source/includes.h Tue Nov 14 22:10:06 1995
- @@ -762,6 +762,9 @@
- #define getpass(s) getsmbpass(s)
- #endif
-
- +#ifndef FD_SETSIZE
- +#define FD_SETSIZE 255
- +#endif
-
- #ifndef MAXINT
- #define MAXINT ((((unsigned)1)<<(sizeof(int)*8-1))-1)
- @@ -969,6 +972,7 @@
-
- #ifdef NOSTRCASECMP
- #define strcasecmp(s1,s2) StrCaseCmp(s1,s2)
- +#define strncasecmp(s1,s2,n) StrnCaseCmp(s1,s2,n)
- #endif
-
- #ifndef strcpy
- diff -u -r --new-file last-version/source/loadparm.c samba-1.9.15/source/loadparm.c
- --- last-version/source/loadparm.c Sun Nov 12 13:12:57 1995
- +++ samba-1.9.15/source/loadparm.c Wed Nov 15 00:05:39 1995
- @@ -142,6 +142,8 @@
- int printing;
- int maxdisksize;
- int lpqcachetime;
- + int os_level;
- + BOOL bPreferredMaster;
- BOOL bEncryptPasswords;
- BOOL bStripDot;
- BOOL bNullPasswords;
- @@ -388,6 +390,8 @@
- #ifdef KANJI
- {"coding system", P_INTEGER, P_GLOBAL, &coding_system, handle_coding_system},
- #endif /* KANJI */
- + {"os level", P_INTEGER, P_GLOBAL, &Globals.os_level, NULL},
- + {"preferred master", P_BOOL, P_GLOBAL, &Globals.bPreferredMaster, NULL},
-
- {"-valid", P_BOOL, P_LOCAL, &sDefault.valid, NULL},
- {"comment", P_STRING, P_LOCAL, &sDefault.comment, NULL},
- @@ -529,6 +533,9 @@
- Globals.bReadbmpx = True;
- Globals.bNullPasswords = False;
- Globals.bStripDot = False;
- + Globals.os_level = 0;
- + Globals.bPreferredMaster = True;
- +
- #ifdef KANJI
- coding_system = interpret_coding_system (KANJI, SJIS_CODE);
- #endif /* KANJI */
- @@ -636,6 +643,7 @@
- FN_GLOBAL_STRING(lp_username_map,&Globals.szUsernameMap)
- FN_GLOBAL_STRING(lp_character_set,&Globals.szCharacterSet)
-
- +FN_GLOBAL_BOOL(lp_preferred_master,&Globals.bPreferredMaster)
- FN_GLOBAL_BOOL(lp_load_printers,&Globals.bLoadPrinters)
- FN_GLOBAL_BOOL(lp_use_rhosts,&Globals.bUseRhosts)
- FN_GLOBAL_BOOL(lp_getwdcache,&use_getwd_cache)
- @@ -648,6 +656,7 @@
- FN_GLOBAL_BOOL(lp_encrypted_passwords,&Globals.bEncryptPasswords)
-
-
- +FN_GLOBAL_INTEGER(lp_os_level,&Globals.os_level)
- FN_GLOBAL_INTEGER(lp_max_log_size,&Globals.max_log_size)
- FN_GLOBAL_INTEGER(lp_mangledstack,&Globals.mangled_stack)
- FN_GLOBAL_INTEGER(lp_maxxmit,&Globals.max_xmit)
- @@ -834,7 +843,7 @@
- sprintf(comment,"Home directory of %s",pszHomename);
- string_set(&iSERVICE(i).comment,comment);
- }
- - iSERVICE(i).bAvailable = True;
- + iSERVICE(i).bAvailable = sDefault.bAvailable;
- iSERVICE(i).bBrowseable = sDefault.bBrowseable;
-
- DEBUG(3,("adding home directory %s at %s\n", pszHomename, pszHomedir));
- diff -u -r --new-file last-version/source/loadparm.h samba-1.9.15/source/loadparm.h
- --- last-version/source/loadparm.h Sun Nov 12 13:08:34 1995
- +++ samba-1.9.15/source/loadparm.h Tue Nov 14 20:59:30 1995
- @@ -56,10 +56,12 @@
- extern char *lp_magicscript(int iService);
- extern char *lp_magicoutput(int iService);
- extern char *lp_mangled_map(int iService);
- +extern int lp_os_level(void);
- extern int lp_max_log_size(void);
- extern int lp_maxxmit(void);
- extern int lp_maxmux(void);
- extern int lp_mangledstack(void);
- +extern BOOL lp_preferred_master(void);
- extern BOOL lp_getwdcache(void);
- extern BOOL lp_use_rhosts(void);
- extern BOOL lp_readprediction(void);
- diff -u -r --new-file last-version/source/nameserv.c samba-1.9.15/source/nameserv.c
- --- last-version/source/nameserv.c Sun Nov 12 12:08:18 1995
- +++ samba-1.9.15/source/nameserv.c Tue Nov 14 21:40:25 1995
- @@ -1,7 +1,7 @@
- /*
- Unix SMB/Netbios implementation.
- Version 1.9.
- - NBT netbios routines and daemon
- + NBT netbios routines and daemon - version 2
- Copyright (C) Andrew Tridgell 1994-1995
-
- This program is free software; you can redistribute it and/or modify
- @@ -17,83 +17,94 @@
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- +
- */
-
- #include "includes.h"
- +#include "loadparm.h"
- +#include "nameserv.h"
-
- -extern pstring debugf;
- +
- +static void queue_packet(struct packet_struct *packet);
- +void process(void);
- +static void dump_names(void);
- +static void announce_request(char *group);
- +
- extern int DEBUGLEVEL;
-
- -extern pstring scope;
- +extern pstring debugf;
- +pstring servicesf = CONFIGFILE;
-
- -static int browse_interval = BROWSE_INTERVAL;
- +extern pstring scope;
-
- -BOOL browse = True;
- -BOOL dns_serve = False;
- +extern BOOL CanRecurse;
-
- -extern struct in_addr lastip;
- -extern int lastport;
- extern struct in_addr myip;
- extern struct in_addr bcast_ip;
- extern struct in_addr Netmask;
- extern pstring myhostname;
- static pstring host_file;
- static pstring myname="";
- -static int num_good_sends=0;
- -static int num_good_receives=0;
- -static pstring lookup="";
- -static int Client138=-1;
- -enum name_sources {LMHOSTS, REGISTER, SELF, DNS};
- -
- -/* this is the structure used for the local netbios name table */
- -typedef struct
- -{
- - time_t start_time;
- - int ttl;
- - struct in_addr ip;
- - struct in_addr master_ip;
- - BOOL found_master;
- - BOOL valid;
- - BOOL isgroup;
- - BOOL unicast;
- - char name[100];
- - int type;
- - int count;
- - enum name_sources source;
- -} name_struct;
-
- +static int ClientNMB=-1;
- +static int ClientDGRAM=-1;
-
- -static int num_names=0;
- -static name_struct *names = NULL;
- +static BOOL needannounce=True;
-
- -extern int Client;
- +/* this is our name database */
- +static struct name_record *namelist = NULL;
-
- -#define NAMEVALID(i) names[i].valid
- -#define ISGROUP(i) (names[i].isgroup)
- +/* list of servers to be returned by NetServerEnum */
- +static struct server_record *serverlist = NULL;
-
- -void process(void);
- +/* this is the domain list. For the moment we will assume that our
- + primary domain is the first one listed in this list */
- +static struct domain_record *domainlist = NULL;
-
- /* are we running as a daemon ? */
- static BOOL is_daemon = False;
-
- -/* machine comment */
- -static pstring comment="";
- +/* machine comment for host announcements */
- +static pstring ServerComment="";
- +
- +static BOOL got_bcast = False;
- +static BOOL got_myip = False;
- +static BOOL got_nmask = False;
-
- -/* die after this number of 10ths of seconds if no activity and not a daemon */
- -static int idle_timeout = NMBD_INETD_TIMEOUT*1000;
- +static BOOL updatedlists = False;
- +static int updatecount=0;
-
- -extern pstring user_socket_options;
- +/* what server type are we currently */
- +static int ServerType =
- +SV_TYPE_WORKSTATION | SV_TYPE_SERVER | SV_TYPE_TIME_SOURCE |
- +SV_TYPE_PRINTQ_SERVER | SV_TYPE_SERVER_UNIX | SV_TYPE_POTENTIAL_BROWSER;
-
- -static void add_group_name(char *name);
- -static void add_host_name(char *name,int type,struct in_addr *ip);
- -static void dump_names(void);
- +/* here are my election parameters */
-
- +/* NTAS uses 2, NT uses 1, WfWg uses 0 */
- +#define MAINTAIN_LIST 1
- +#define ELECTION_VERSION 1
-
- -static BOOL got_bcast = False;
- -static BOOL got_myip = False;
- -static BOOL got_nmask = False;
- +static BOOL RunningElection = False;
- +static BOOL needelection = False;
- +static int ElectionCount = 0;
- +static int StartupTime =0;
-
-
- +/* WfWg uses 01040b01 */
- +/* Win95 uses 01041501 */
- +/* NTAS uses ?? */
- +static uint32 ElectionCriterion = (MAINTAIN_LIST<<1)|(ELECTION_VERSION<<8);
- +
- +/* we currently support being the master for just one group. Being the
- + master for more than one group might be tricky as NetServerEnum is
- + often asked for a list without naming the group */
- +static fstring PrimaryGroup="";
- +
- +#define AM_MASTER (PrimaryGroup[0] && (ServerType & SV_TYPE_MASTER_BROWSER))
- +
- +#define MSBROWSE "\001\002__MSBROWSE__\002"
- +
- /****************************************************************************
- catch a sighup
- ****************************************************************************/
- @@ -101,10 +112,9 @@
- {
- BlockSignals(True);
-
- - DEBUG(0,("Got SIGHUP - not implemented\n"));
- + DEBUG(0,("Got SIGHUP (reload not implemented)\n"));
- dump_names();
- - if (!is_daemon)
- - exit(1);
- + reload_services(True);
-
- BlockSignals(False);
- #ifndef DONT_REINSTALL_SIG
- @@ -127,6 +137,43 @@
- return(0);
- }
-
- +#if DUMP_CORE
- +/*******************************************************************
- +prepare to dump a core file - carefully!
- +********************************************************************/
- +static BOOL dump_core(void)
- +{
- + char *p;
- + pstring dname;
- + strcpy(dname,debugf);
- + if ((p=strrchr(dname,'/'))) *p=0;
- + strcat(dname,"/corefiles");
- + mkdir(dname,0700);
- + chown(dname,getuid(),getgid());
- + chmod(dname,0700);
- + if (chdir(dname)) return(False);
- + umask(~(0700));
- +
- +#ifndef NO_GETRLIMIT
- +#ifdef RLIMIT_CORE
- + {
- + struct rlimit rlp;
- + getrlimit(RLIMIT_CORE, &rlp);
- + rlp.rlim_cur = MAX(4*1024*1024,rlp.rlim_cur);
- + setrlimit(RLIMIT_CORE, &rlp);
- + getrlimit(RLIMIT_CORE, &rlp);
- + DEBUG(3,("Core limits now %d %d\n",rlp.rlim_cur,rlp.rlim_max));
- + }
- +#endif
- +#endif
- +
- +
- + DEBUG(0,("Dumping core in %s\n",dname));
- + return(True);
- +}
- +#endif
- +
- +
- /****************************************************************************
- possibly continue after a fault
- ****************************************************************************/
- @@ -139,1536 +186,1585 @@
- if (is_daemon && errcount<100)
- process();
-
- - exit(1);
- +#if DUMP_CORE
- + if (dump_core()) return;
- +#endif
- +
- + return;
- }
-
- /****************************************************************************
- true if two netbios names are equal
- ****************************************************************************/
- -static BOOL name_equal(char *s1,char *s2,int type1,int type2)
- +static BOOL name_equal(struct nmb_name *n1,struct nmb_name *n2)
- {
- - char n1[20],n2[20];
- + if (n1->name_type != n2->name_type) return(False);
- +
- + return(strequal(n1->name,n2->name) && strequal(n1->scope,n2->scope));
- +}
-
- - if (type1 != type2) return(False);
- +/****************************************************************************
- + add a netbios name into the namelist
- + **************************************************************************/
- +static void add_name(struct name_record *n)
- +{
- + struct name_record *n2;
-
- - StrnCpy(n1,s1,15);
- - StrnCpy(n2,s2,15);
- + if (!namelist) {
- + namelist = n;
- + n->prev = NULL;
- + n->next = NULL;
- + return;
- + }
-
- - trim_string(n1,NULL," ");
- - trim_string(n2,NULL," ");
- + for (n2 = namelist; n2->next; n2 = n2->next) ;
-
- - return(strequal(n1,n2));
- + n2->next = n;
- + n->next = NULL;
- + n->prev = n2;
- }
-
- /****************************************************************************
- -add a netbios name
- -****************************************************************************/
- -static int add_name(void)
- + add a domain into the list
- + **************************************************************************/
- +static void add_domain(struct domain_record *d)
- {
- - int i;
- + struct domain_record *d2;
-
- - for (i=0;i<num_names;i++)
- - if (!names[i].valid)
- - break;
- -
- - if (i==num_names) {
- - name_struct *n;
- - if (num_names == 0)
- - n = (name_struct *)malloc(sizeof(name_struct));
- - else
- - n = (name_struct *)realloc(names,sizeof(name_struct)*(num_names+1));
- - if (!n) {
- - DEBUG(0,("Can't malloc more names space!\n"));
- - return(-1);
- - }
- - i = num_names;
- - num_names++;
- - names = n;
- + if (!domainlist) {
- + domainlist = d;
- + d->prev = NULL;
- + d->next = NULL;
- + return;
- }
-
- - bzero(&names[i],sizeof(names[i]));
- + for (d2 = domainlist; d2->next; d2 = d2->next) ;
-
- - return(i);
- + d2->next = d;
- + d->next = NULL;
- + d->prev = d2;
- }
-
- +
- /****************************************************************************
- -find a name
- -****************************************************************************/
- -static int find_name(char *s,int type,BOOL groups)
- + add a server into the list
- + **************************************************************************/
- +static void add_server(struct server_record *s)
- {
- - int i;
- - time_t t = time(NULL);
- + struct server_record *s2;
-
- - for (i=0;i<num_names;i++)
- - if (names[i].valid && (groups || !ISGROUP(i)))
- - {
- - if ((names[i].ttl > 0) && (t > (names[i].start_time + names[i].ttl)))
- - names[i].valid = False;
- - else
- - {
- - if (name_equal(s,names[i].name,type,names[i].type)) {
- - return(i);
- - }
- - }
- - }
- - return -1;
- + if (!serverlist) {
- + serverlist = s;
- + s->prev = NULL;
- + s->next = NULL;
- + return;
- + }
- +
- + for (s2 = serverlist; s2->next; s2 = s2->next) ;
- +
- + s2->next = s;
- + s->next = NULL;
- + s->prev = s2;
- }
-
- +/****************************************************************************
- + remove a name from the namelist. The pointer must be an element just
- + retrieved
- + **************************************************************************/
- +static void remove_name(struct name_record *n)
- +{
- + struct name_record *nlist = namelist;
- + while (nlist && nlist != n) nlist = nlist->next;
- + if (nlist) {
- + if (nlist->next) nlist->next->prev = nlist->prev;
- + if (nlist->prev) nlist->prev->next = nlist->next;
- + free(nlist);
- + }
- +}
-
- /****************************************************************************
- -check names, and change any 0 IPs to myip
- -****************************************************************************/
- -static void check_names(void)
- + find a name in the namelist
- + **************************************************************************/
- +static struct name_record *find_name(struct nmb_name *n)
- {
- - int i;
- - int group_count=0;
- + struct name_record *ret;
- + for (ret = namelist; ret; ret = ret->next)
- + if (name_equal(&ret->name,n)) return(ret);
-
- - /* add the magic __SAMBA__ name */
- - add_host_name("__SAMBA__",0x20,&myip);
- - add_host_name("__SAMBA__",0x0,&myip);
- + return(NULL);
- +}
-
- - for (i=0;i<num_names;i++)
- - if (names[i].valid) {
- - if (ISGROUP(i)) group_count++;
- - }
- +/****************************************************************************
- + dump a copy of the name table
- + **************************************************************************/
- +static void dump_names(void)
- +{
- + time_t t = time(NULL);
- + struct name_record *n;
- + struct domain_record *d;
-
- - if (group_count == 0)
- - add_group_name(WORKGROUP);
- + DEBUG(3,("Dump of local name table:\n"));
-
- + for (n = namelist; n; n = n->next) {
- + DEBUG(3,("%s %s TTL=%d Unique=%s\n",
- + namestr(&n->name),
- + inet_ntoa(n->ip),
- + n->death_time?n->death_time-t:0,
- + BOOLSTR(n->unique)));
- + }
-
- - for (i=0;i<num_names;i++)
- - if (names[i].valid && strequal((char *)inet_ntoa(names[i].ip),"0.0.0.0"))
- - names[i].ip = (ISGROUP(i)?bcast_ip:myip);
- + DEBUG(3,("\nDump of domain list:\n"));
- + for (d = domainlist; d; d = d->next)
- + DEBUG(3,("%s %s\n",d->name,inet_ntoa(d->bcast_ip)));
- }
-
-
- /****************************************************************************
- -dump a copy of the name table
- -****************************************************************************/
- -static void dump_names(void)
- + add a host entry to the name list
- + ****************************************************************************/
- +static struct name_record *add_host_entry(char *name,int type,BOOL unique,int ttl,
- + enum name_source source,
- + struct in_addr ip)
- {
- - int i;
- - DEBUG(3,("Dump of local name table\n"));
- - for (i=0;i<num_names;i++)
- - if (names[i].valid) {
- - DEBUG(3,("%s %s %d %s",
- - names[i].name,inet_ntoa(names[i].ip),
- - names[i].ttl,BOOLSTR(names[i].isgroup)));
- - if (names[i].found_master)
- - DEBUG(3,(" %s",inet_ntoa(names[i].master_ip)));
- - DEBUG(3,("\n"));
- - }
- + struct name_record *n;
- + struct name_record *n2=NULL;
- +
- + n = (struct name_record *)malloc(sizeof(*n));
- + if (!n) return(NULL);
- +
- + bzero((char *)n,sizeof(*n));
- +
- + make_nmb_name(&n->name,name,type,scope);
- + if ((n2=find_name(&n->name))) {
- + free(n);
- + n = n2;
- + }
- +
- + if (ttl) n->death_time = time(NULL)+ttl*3;
- + n->ip = ip;
- + n->unique = unique;
- + n->source = source;
- +
- + if (!n2) add_name(n);
- +
- + DEBUG(3,("Added host entry %s at %s ttl=%d unique=%s\n",
- + namestr(&n->name),inet_ntoa(ip),ttl,BOOLSTR(unique)));
- +
- + return(n);
- }
-
-
- /****************************************************************************
- -load a netbios hosts file
- -****************************************************************************/
- -static void load_hosts_file(char *fname)
- + add a domain entry
- + ****************************************************************************/
- +static struct domain_record *add_domain_entry(char *name,struct in_addr ip)
- {
- - int i;
- - FILE *f = fopen(fname,"r");
- - pstring line;
- - if (!f)
- - {
- - DEBUG(2,("Not using non-existant lmhosts file %s\n",fname));
- - return;
- - }
- + struct domain_record *d;
-
- - while (!feof(f))
- - {
- - if (!fgets_slash(line,sizeof(pstring),f)) continue;
- -
- - if (*line == '#') continue;
- + d = (struct domain_record *)malloc(sizeof(*d));
-
- - {
- - string ip="",name="",flags="",extra="";
- - unsigned long a;
- - char *ptr;
- - int count = 0;
- - ptr = line;
- - if (next_token(&ptr,ip,NULL)) ++count;
- - if (next_token(&ptr,name,NULL)) ++count;
- - if (next_token(&ptr,flags,NULL)) ++count;
- - if (next_token(&ptr,extra,NULL)) ++count;
- + if (!d) return(NULL);
-
- - if (count <= 0) continue;
- + bzero((char *)d,sizeof(*d));
-
- - if (count > 0 && count < 2)
- - {
- - DEBUG(0,("Ill formed hosts line [%s]\n",line));
- - continue;
- - }
- + StrnCpy(d->name,name,sizeof(d->name)-1);
- + d->bcast_ip = ip;
-
- - i = add_name();
- - if (i < 0)
- - {
- - fclose(f);
- - return;
- - }
- + if (!*PrimaryGroup && ip_equal(bcast_ip,ip) && name[0] != '*') {
- + strcpy(PrimaryGroup,name);
- + strupper(PrimaryGroup);
- + }
-
- - a = interpret_addr(ip);
- - putip((char *)&names[i].ip,(char *)&a);
- + add_domain(d);
-
- - names[i].valid = True;
- - names[i].source = LMHOSTS;
- + ip = *interpret_addr2("255.255.255.255");
- + if (name[0] != '*') add_host_entry(name,0x1e,False,0,SELF,ip);
-
- - StrnCpy(names[i].name,name,15);
- - if (strchr(flags,'G') || strchr(flags,'S'))
- - names[i].isgroup = True;
- - if (strchr(flags,'M') && !ISGROUP(i))
- - strcpy(myname,name);
- - if (strchr(flags,'U'))
- - names[i].unicast = True;
- - if (names[i].isgroup)
- - names[i].type = 0xF0; /* hopefully invalid */
- - else
- - names[i].type = 0x20;
- - }
- - }
- + DEBUG(3,("Added domain entry %s at %s\n",
- + name,inet_ntoa(ip)));
-
- - fclose(f);
- + return(d);
- }
-
- -
- /****************************************************************************
- -add a netbios group name
- -****************************************************************************/
- -static void add_group_name(char *name)
- + add a server entry
- + ****************************************************************************/
- +static struct server_record *add_server_entry(char *name,int servertype,
- + int ttl,char *comment)
- {
- - int i = add_name();
- - if (i < 0)
- - return;
- + BOOL newentry=False;
- + struct server_record *s;
- +
- + updatedlists=True;
- +
- + for (s = serverlist; s; s = s->next)
- + if (strequal(name,s->name)) break;
- +
- + if (!s) {
- + newentry = True;
- + s = (struct server_record *)malloc(sizeof(*s));
- +
- + if (!s) return(NULL);
- +
- + bzero((char *)s,sizeof(*s));
- + }
- +
- + /* update the entry */
- + StrnCpy(s->name,name,sizeof(s->name)-1);
- + StrnCpy(s->comment,comment,sizeof(s->comment)-1);
- + s->servertype = servertype;
- + s->death_time = ttl?time(NULL)+ttl*3:0;
- + strupper(s->name);
- + if (s->servertype & SV_TYPE_DOMAIN_ENUM) strupper(s->comment);
- +
- + if (!newentry) return(s);
-
- - bzero((char *)&names[i].ip,sizeof(names[i].ip));
- + add_server(s);
-
- - strcpy(names[i].name,name);
- - names[i].isgroup = True;
- - names[i].valid = True;
- - names[i].type = 0xF0;
- - names[i].source = SELF;
- + DEBUG(3,("Added server entry %s of type %x (%s)\n",
- + name,servertype,comment));
- +
- + return(s);
- }
-
- +
- /****************************************************************************
- -add a host name
- -****************************************************************************/
- -static void add_host_name(char *name,int type,struct in_addr *ip)
- + add the magic samba names, useful for finding samba servers
- + **************************************************************************/
- +static void add_my_names(void)
- {
- - int i;
- + struct in_addr ip = *interpret_addr2("0.0.0.0");
-
- - if (find_name(name,type,True) >= 0) return;
- + add_host_entry("__SAMBA__",0x20,True,0,SELF,ip);
- + add_host_entry("__SAMBA__",0x0,True,0,SELF,ip);
- + add_host_entry(myname,0x20,True,0,SELF,ip);
- + add_host_entry(myname,0x0,True,0,SELF,ip);
- + add_host_entry(myname,0x1f,True,0,SELF,ip); /* used for chat, I think */
- + if (!domainlist)
- + add_domain_entry(lp_workgroup(),bcast_ip);
- + add_server_entry(myname,
- + ServerType,
- + 0,ServerComment);
- +}
-
- - i = add_name();
- - if (i < 0)
- - return;
-
- - names[i].ip = *ip;
- - strcpy(names[i].name,name);
- - names[i].valid = True;
- - names[i].start_time = time(NULL);
- - names[i].ttl = 0;
- - names[i].type = type;
- - names[i].source = SELF;
- +/*******************************************************************
- + write out browse.dat
- + ******************************************************************/
- +static void write_browse_list(void)
- +{
- + struct server_record *s;
- + pstring fname,fnamenew;
- + FILE *f;
- +
- + updatecount++;
- +
- + strcpy(fname,lp_lockdir());
- + trim_string(fname,NULL,"/");
- + strcat(fname,"/");
- + strcat(fname,SERVER_LIST);
- + strcpy(fnamenew,fname);
- + strcat(fnamenew,".");
- +
- + f = fopen(fnamenew,"w");
- +
- + if (!f) {
- + DEBUG(4,("Can't open %s - %s\n",fnamenew,strerror(errno)));
- + return;
- + }
- +
- + for (s=serverlist; s ; s = s->next) {
- + /* don't list domains I don't have a master for */
- + if ((s->servertype & SV_TYPE_DOMAIN_ENUM) && !s->comment[0]) continue;
- +
- + fprintf(f,"\"%s\"\t%08x\t\"%s\"\n",s->name,s->servertype,s->comment);
- + }
- +
- +
- + fclose(f);
- + unlink(fname);
- + rename(fnamenew,fname);
- + DEBUG(3,("Wrote browse list %s\n",fname));
- }
-
- -/****************************************************************************
- -word out the length of a nmb message
- -****************************************************************************/
- -static int nmb_len(char *buf)
- +/*******************************************************************
- + expire old names in the namelist and serverlist
- + ******************************************************************/
- +static void expire_names(void)
- {
- -int i;
- -int ret = 12;
- -char *p = buf;
- -int qdcount = RSVAL(buf,4);
- -int ancount = RSVAL(buf,6);
- -int nscount = RSVAL(buf,8);
- -int arcount = RSVAL(buf,10);
- + static time_t lastrun=0;
- + time_t t = time(NULL);
- + struct name_record *n;
- + struct name_record *next;
- + struct server_record *s;
- + struct server_record *nexts;
- +
- + if (!lastrun) lastrun = t;
- + if (t < lastrun + 5) return;
- + lastrun = t;
- +
- + /* expire old names */
- + for (n = namelist; n; n = next) {
- + if (n->death_time && n->death_time < t) {
- + DEBUG(3,("Removing dead name %s\n",
- + namestr(&n->name)));
- + next = n->next;
- + if (n->prev) n->prev->next = n->next;
- + if (n->next) n->next->prev = n->prev;
- + if (namelist == n) namelist = n->next;
- + free(n);
- + } else {
- + next = n->next;
- + }
- + }
-
- -/* check for insane qdcount values? */
- -if (qdcount > 100 || qdcount < 0)
- - {
- - DEBUG(6,("Invalid qdcount? qdcount=%d\n",qdcount));
- - return(0);
- + /* expire old entries in the serverlist */
- + for (s = serverlist; s; s = nexts) {
- + if (s->death_time && s->death_time < t) {
- + DEBUG(3,("Removing dead server %s\n",s->name));
- + updatedlists = True;
- + nexts = s->next;
- + if (s->prev) s->prev->next = s->next;
- + if (s->next) s->next->prev = s->prev;
- + if (serverlist == s) serverlist = s->next;
- + free(s);
- + } else {
- + nexts = s->next;
- + }
- }
- +}
-
- -for (i=0;i<qdcount;i++)
- - {
- - p = buf + ret;
- - ret += name_len(p) + 4;
- +
- +/*******************************************************************
- + delete old names from the namelist
- + ******************************************************************/
- +static void housekeeping(void)
- +{
- + time_t t = time(NULL);
- +
- + expire_names();
- +
- + /* write out the browse.dat database for smbd to get */
- + if (updatedlists) {
- + write_browse_list();
- + updatedlists = False;
- }
-
- -for (i=0;i<(ancount + nscount + arcount);i++)
- {
- - int rdlength;
- - p = buf + ret;
- - ret += name_len(p) + 8;
- - p = buf + ret;
- - rdlength = RSVAL(p,0);
- - ret += rdlength + 2;
- + /* occasionally check to see if the master browser is around */
- + static time_t lastrun=0;
- + if (!lastrun) lastrun = t;
- + if (t < lastrun + 5*60) return;
- + lastrun = t;
- +
- + if (!AM_MASTER && *PrimaryGroup &&
- + !name_query(ClientNMB,PrimaryGroup,0x1d,True,False,
- + bcast_ip,NULL,queue_packet)) {
- + DEBUG(2,("Forcing election on %s\n",PrimaryGroup));
- + needelection = True;
- + }
- }
- -
- -return(ret);
- }
-
- +
- /****************************************************************************
- -receive a name message. timeout is in milliseconds
- -****************************************************************************/
- -static int receive_nmb(char *buffer,int timeout)
- + reload the services file
- + **************************************************************************/
- +BOOL reload_services(BOOL test)
- {
- - int ret = read_max_udp(Client,buffer,sizeof(pstring),timeout);
- + BOOL ret;
- + extern fstring remote_machine;
- +
- + strcpy(remote_machine,"nmbd");
-
- - if (ret < 0)
- + if (lp_loaded())
- {
- - DEBUG(0,("No bytes from client\n"));
- - if (!is_daemon)
- + pstring fname;
- + strcpy(fname,lp_configfile());
- + if (file_exist(fname,NULL) && !strcsequal(fname,servicesf))
- {
- - close_sockets();
- - exit(0);
- + strcpy(servicesf,fname);
- + test = False;
- }
- }
- -
- - if (ret <= 1)
- - return 0;
-
- - log_in(buffer,ret);
- + if (test && !lp_file_list_changed())
- + return(True);
-
- - DEBUG(3,("received packet from (%s) nmb_len=%d len=%d\n",
- - inet_ntoa(lastip),nmb_len(buffer),ret));
- + ret = lp_load(servicesf,True);
-
- - num_good_receives++;
- + /* perhaps the config filename is now set */
- + if (!test)
- + reload_services(True);
-
- return(ret);
- }
-
- +
- +
- /****************************************************************************
- -send a name message
- +load a netbios hosts file
- ****************************************************************************/
- -static BOOL send_nmb(char *buf, int len, struct in_addr *ip,int port)
- +static void load_hosts_file(char *fname)
- {
- - BOOL ret;
- - struct sockaddr_in sock_out;
- + FILE *f = fopen(fname,"r");
- + pstring line;
- + if (!f) {
- + DEBUG(2,("Can't open lmhosts file %s\n",fname));
- + return;
- + }
-
- - /* set the address and port */
- - bzero((char *)&sock_out,sizeof(sock_out));
- - putip((char *)&sock_out.sin_addr,(char *)ip);
- - sock_out.sin_port = htons( port );
- - sock_out.sin_family = AF_INET;
- -
- - /* log the packet */
- - log_out(buf,len);
- -
- - if (DEBUGLEVEL > 0)
- - DEBUG(3,("sending a packet of len %d to (%s) on port 137 of type DGRAM\n",
- - len,inet_ntoa(*ip)));
- -
- - /* send it */
- - ret = (sendto(Client,buf,len,0,(struct sockaddr *)&sock_out,sizeof(sock_out)) >= 0);
- + while (!feof(f))
- + {
- + if (!fgets_slash(line,sizeof(pstring),f)) continue;
- +
- + if (*line == '#') continue;
-
- - if (!ret)
- - DEBUG(0,("Send packet failed. ERRNO=%d\n",errno));
- + {
- + BOOL group=False;
- + string ip="",name="",flags="",extra="";
- + char *ptr;
- + int count = 0;
- + struct in_addr ipaddr;
- + enum name_source source = LMHOSTS;
-
- - if (ret)
- - num_good_sends++;
- + ptr = line;
-
- - return(ret);
- -}
- + if (next_token(&ptr,ip,NULL)) ++count;
- + if (next_token(&ptr,name,NULL)) ++count;
- + if (next_token(&ptr,flags,NULL)) ++count;
- + if (next_token(&ptr,extra,NULL)) ++count;
-
- -/*******************************************************************
- -check if an IP is on my net
- -********************************************************************/
- -static BOOL is_mynet(struct in_addr ip)
- -{
- - unsigned int net1,net2,nmask,subnet1,subnet2;
- + if (count <= 0) continue;
-
- - nmask = *(unsigned int *)&Netmask;
- - net1 = (*(unsigned int *)&myip);
- - subnet1 = net1 & nmask;
- - net2 = (*(unsigned int *)&ip);
- - subnet2 = net2 & nmask;
- -
- - return((net1 != net2) && (subnet1 == subnet2));
- -}
- + if (count > 0 && count < 2)
- + {
- + DEBUG(0,("Ill formed hosts line [%s]\n",line));
- + continue;
- + }
-
- -/****************************************************************************
- -interpret a node status response
- -****************************************************************************/
- -static void interpret_node_status(char *inbuf, char *master)
- -{
- - int level = master?3:0;
- - char *p = inbuf + 12 + name_len(inbuf+12) + 10;
- - int numnames = CVAL(p,0);
- - DEBUG(level,("received %d names\n",numnames));
- + if (strchr(flags,'G') || strchr(flags,'S'))
- + group = True;
-
- - p += 1;
- - while (numnames--)
- - {
- - char qname[17];
- - int type;
- - fstring flags="";
- - StrnCpy(qname,p,15);
- - type = CVAL(p,15);
- - p += 16;
- -
- - if (p[0] & 0x80) strcat(flags,"<GROUP> ");
- - if (p[0] & 0x60 == 0) strcat(flags,"B ");
- - if (p[0] & 0x60 == 1) strcat(flags,"P ");
- - if (p[0] & 0x60 == 2) strcat(flags,"M ");
- - if (p[0] & 0x60 == 3) strcat(flags,"_ ");
- - if (p[0] & 0x10) strcat(flags,"<DEREGISTERING> ");
- - if (p[0] & 0x08) strcat(flags,"<CONFLICT> ");
- - if (p[0] & 0x04) strcat(flags,"<ACTIVE> ");
- - if (p[0] & 0x02) strcat(flags,"<PERMANENT> ");
- + if (strchr(flags,'M') && !group) {
- + source = SELF;
- + strcpy(myname,name);
- + }
- +
- + ipaddr = *interpret_addr2(ip);
-
- - if (master && type == 0x1d) {
- - StrnCpy(master,qname,15);
- + if (group) {
- + add_domain_entry(name,ipaddr);
- + } else {
- + add_host_entry(name,0x20,True,0,source,ipaddr);
- + }
- }
- -
- - DEBUG(level,("\t%s (type=0x%x)\t%s\n",qname,type,flags));
- - p+=2;
- }
- - DEBUG(level,("num_good_sends=%d num_good_receives=%d\n",
- - IVAL(p,20),IVAL(p,24)));
- +
- + fclose(f);
- }
-
- +/*******************************************************************
- + check if 2 IPs are on the same net
- + we will assume the local netmask, although this could be wrong XXXX
- + ******************************************************************/
- +static BOOL same_net(struct in_addr ip1,struct in_addr ip2)
- +{
- + unsigned long net1,net2,nmask;
- +
- + nmask = ntohl(Netmask.s_addr);
- + net1 = ntohl(ip1.s_addr);
- + net2 = ntohl(ip2.s_addr);
- +
- + return((net1 & nmask) == (net2 & nmask));
- +}
-
- /****************************************************************************
- -show a nmb message
- -****************************************************************************/
- -static void show_nmb(char *inbuf)
- + send an election packet
- + **************************************************************************/
- +static void send_election(char *group,uint32 criterion,int timeup,char *name)
- {
- - int i,l;
- - int name_trn_id = RSVAL(inbuf,0);
- - int opcode = (CVAL(inbuf,2) >> 3) & 0xF;
- - int nm_flags = ((CVAL(inbuf,2) & 0x7) << 4) + (CVAL(inbuf,3)>>4);
- - int rcode = CVAL(inbuf,3) & 0xF;
- - int qdcount = RSVAL(inbuf,4);
- - int ancount = RSVAL(inbuf,6);
- - int nscount = RSVAL(inbuf,8);
- - int arcount = RSVAL(inbuf,10);
- - char name[100];
- + pstring outbuf;
- + char *p;
-
- - if (DEBUGLEVEL < 3) return;
- + DEBUG(2,("Sending election to %s for workgroup %s\n",
- + inet_ntoa(bcast_ip),group));
-
- - DEBUG(3,("\nPACKET INTERPRETATION\n"));
- + bzero(outbuf,sizeof(outbuf));
- + p = outbuf;
- + CVAL(p,0) = 8; /* election */
- + p++;
-
- - if (opcode == 5 && ((nm_flags & ~1) == 0x10) && rcode == 0)
- - DEBUG(3,("NAME REGISTRATION REQUEST (%s)\n",nm_flags&1?"Broadcast":"Unicast"));
- + CVAL(p,0) = ELECTION_VERSION;
- + SIVAL(p,1,criterion);
- + SIVAL(p,5,timeup*1000); /* ms - despite the spec */
- + p += 13;
- + strcpy(p,name);
- + strupper(p);
- + p = skip_string(p,1);
-
- - if (opcode == 5 && ((nm_flags & ~1) == 0x00) && rcode == 0)
- - DEBUG(3,("NAME OVERWRITE REQUEST AND DEMAND (%s)\n",nm_flags&1?"Broadcast":"Unicast"));
- -
- - if (opcode == 9 && ((nm_flags & ~1) == 0x00) && rcode == 0)
- - DEBUG(3,("NAME REFRESH REQUEST (%s)\n",nm_flags&1?"Broadcast":"Unicast"));
- + send_udp_dgram(ClientDGRAM,outbuf,PTR_DIFF(p,outbuf),
- + name,group,0,0x1e,bcast_ip,myip);
- +}
-
- - if (opcode == 8)
- - DEBUG(3,("NAME REFRESH (%s)\n",nm_flags&1?"Broadcast":"Unicast"));
- -
- - if (opcode == 5 && nm_flags == 0x58 && rcode == 0)
- - DEBUG(3,("POSITIVE NAME REGISTRATION RESPONSE\n"));
- -
- - if (opcode == 5 && nm_flags == 0x58 && rcode != 0 && rcode != 7)
- - DEBUG(3,("NEGATIVE NAME REGISTRATION RESPONSE\n"));
- -
- - if (opcode == 5 && nm_flags == 0x50 && rcode == 0)
- - DEBUG(3,("END-NODE CHALLENGE REGISTRATION RESPONSE\n"));
- -
- - if (opcode == 5 && nm_flags == 0x58 && rcode != 0 && rcode == 7)
- - DEBUG(3,("NAME CONFLICT DEMAND\n"));
- -
- - if (opcode == 6 && (nm_flags&~1) == 0x00 && rcode == 0)
- - DEBUG(3,("NAME RELEASE REQUEST & DEMAND (%s)\n",nm_flags&1?"Broadcast":"Unicast"));
- -
- - if (opcode == 6 && (nm_flags&~1) == 0x40 && rcode == 0)
- - DEBUG(3,("POSITIVE NAME RELEASE RESPONSE\n"));
- -
- - if (opcode == 6 && (nm_flags&~1) == 0x40 && rcode != 0)
- - DEBUG(3,("NEGATIVE NAME RELEASE RESPONSE\n"));
- -
- - if (opcode == 0 && (nm_flags&~1) == 0x10 && rcode == 0)
- - DEBUG(3,("NAME QUERY REQUEST (%s)\n",nm_flags&1?"Broadcast":"Unicast"));
- -
- - if (opcode == 0 && (nm_flags&~0x28) == 0x50 && rcode == 0)
- - DEBUG(3,("POSITIVE NAME QUERY RESPONSE\n"));
- -
- - if (opcode == 0 && (nm_flags&~0x08) == 0x50 && rcode != 0)
- - DEBUG(3,("NEGATIVE NAME QUERY RESPONSE\n"));
- -
- - if (opcode == 0 && nm_flags == 0x10 && rcode == 0)
- - DEBUG(3,("REDIRECT NAME QUERY RESPONSE\n"));
-
- - if (opcode == 7 && nm_flags == 0x80 && rcode == 0)
- - DEBUG(3,("WAIT FOR ACKNOWLEDGEMENT RESPONSE\n"));
- -
- - if (opcode == 0 && (nm_flags&~1) == 0x00 && rcode == 0)
- - DEBUG(3,("NODE STATUS REQUEST (%s)\n",nm_flags&1?"Broadcast":"Unicast"));
- +/****************************************************************************
- + send a backup list response
- + **************************************************************************/
- +static void send_backup_list(char *name,int token,struct nmb_name *to,
- + struct in_addr ip)
- +{
- + pstring outbuf;
- + char *p;
-
- - if (opcode == 0 && nm_flags == 0x40 && rcode == 0)
- - {
- - DEBUG(3,("NODE STATUS RESPONSE\n"));
- - interpret_node_status(inbuf,NULL);
- - }
- -
- -
- - DEBUG(3,("name_trn_id=0x%x\nopcode=0x%x\nnm_flags=0x%x\nrcode=0x%x\n",
- - name_trn_id,opcode,nm_flags,rcode));
- - DEBUG(3,("qdcount=%d\nancount=%d\nnscount=%d\narcount=%d\n",
- - qdcount,ancount,nscount,arcount));
- + DEBUG(2,("Sending backup list to %s for workgroup %s\n",
- + inet_ntoa(ip),PrimaryGroup));
-
- - l = 12;
- - for (i=0;i<qdcount;i++)
- - {
- - int type,class;
- - DEBUG(3,("QUESTION %d\n",i));
- - name_extract(inbuf,l,name);
- - l += name_len(inbuf+l);
- - type = RSVAL(inbuf+l,0);
- - class = RSVAL(inbuf+l,2);
- - l += 4;
- - DEBUG(3,("\t%s\n\ttype=0x%x\n\tclass=0x%x\n",name,type,class));
- - }
- + bzero(outbuf,sizeof(outbuf));
- + p = outbuf;
- + CVAL(p,0) = 10; /* backup list response */
- + p++;
-
- - for (i=0;i<(ancount + nscount + arcount);i++)
- - {
- - int type,class,ttl,rdlength;
- - DEBUG(3,("RESOURCE %d\n",i));
- - name_extract(inbuf,l,name);
- - l += name_len(inbuf + l);
- - type = RSVAL(inbuf+l,0);
- - class = RSVAL(inbuf+l,2);
- - ttl = RIVAL(inbuf+l,4);
- - rdlength = RSVAL(inbuf+l,8);
- - l += 10 + rdlength;
- - DEBUG(3,("\t%s\n\ttype=0x%x\n\tclass=0x%x\n",name,type,class));
- - DEBUG(3,("\tttl=%d\n\trdlength=%d\n",ttl,rdlength));
- - }
- + CVAL(p,0) = 1; /* count */
- + SIVAL(p,1,token);
- + p += 5;
- + strcpy(p,name);
- + strupper(p);
- + p = skip_string(p,1) + 1;
-
- - DEBUG(3,("\n"));
- -
- + send_udp_dgram(ClientDGRAM,outbuf,PTR_DIFF(p,outbuf),
- + myname,to->name,0,to->name_type,ip,myip);
- }
-
-
- -/****************************************************************************
- -do a netbios name query to find someones IP
- -****************************************************************************/
- -static BOOL name_query(char *name, char name_type, BOOL bcast,
- - struct in_addr to_ip, struct in_addr *ip, void (*fn)())
- +/*******************************************************************
- + become the master browser
- + ******************************************************************/
- +static void become_master(void)
- {
- - BOOL found=False;
- - pstring inbuf,outbuf;
- - static uint16 name_trn_id = 0x6242;
- - char *p;
- - int retries = 3;
- - int retry_time = bcast?250:5000;
- - struct timeval tval;
- -
- - bzero(inbuf,sizeof(inbuf));
- - bzero(outbuf,sizeof(outbuf));
- -
- - name_trn_id += getpid() % 100;
- - name_trn_id = (name_trn_id % 0x7FFF);
- + DEBUG(2,("Becoming master for %s\n",PrimaryGroup));
-
- - RSSVAL(outbuf,0,name_trn_id);
- - CVAL(outbuf,2) = 0x1;
- - CVAL(outbuf,3) = bcast?(1<<4):0;
- - RSSVAL(outbuf,4,1);
- - RSSVAL(outbuf,6,0);
- - RSSVAL(outbuf,8,0);
- - RSSVAL(outbuf,10,0);
- - p = outbuf+12;
- - name_mangle(name,p,name_type);
- - p += name_len(p);
- - RSSVAL(p,0,0x20);
- - RSSVAL(p,2,0x1);
- - p += 4;
- -
- - DEBUG(2,("Sending name query for %s\n",name));
- -
- - show_nmb(outbuf);
- -
- - GetTimeOfDay(&tval);
- -
- - if (!send_nmb(outbuf,nmb_len(outbuf), &to_ip, 137))
- - return False;
- - retries--;
- + ServerType |= SV_TYPE_MASTER_BROWSER;
- + ServerType |= SV_TYPE_BACKUP_BROWSER;
- + ElectionCriterion |= 0x5;
-
- - while (1)
- - {
- - struct timeval tval2;
- - GetTimeOfDay(&tval2);
- - if (TvalDiff(&tval,&tval2) > retry_time) {
- - if (!retries) break;
- - if (!found && !send_nmb(outbuf,nmb_len(outbuf), &to_ip, 137))
- - return False;
- - GetTimeOfDay(&tval);
- - retries--;
- - }
- + add_host_entry(PrimaryGroup,0x1d,True,0,SELF,myip);
- + add_host_entry(PrimaryGroup,0x0,False,0,SELF,myip);
- + add_host_entry(MSBROWSE,1,False,0,SELF,myip);
- + add_server_entry(PrimaryGroup,SV_TYPE_DOMAIN_ENUM,0,myname);
- + add_server_entry(myname,ServerType,0,ServerComment);
-
- - if (receive_nmb(inbuf,90))
- - {
- - int rec_name_trn_id = RSVAL(inbuf,0);
- - int opcode = (CVAL(inbuf,2) >> 3) & 0xF;
- - int rcode = CVAL(inbuf,3) & 0xF;
- - int response = (CVAL(inbuf,2)>>7);
- - int qdcount = RSVAL(inbuf,4);
- - int ancount = RSVAL(inbuf,6);
- - show_nmb(inbuf);
- -
- - /* is it a positive response to our request? */
- - if ((rec_name_trn_id == name_trn_id) && response) {
- - if (opcode == 0 && qdcount==0 && ancount==1 && rcode == 0) {
- - putip((char *)ip,inbuf + 12 + name_len(inbuf+12) + 12);
- - DEBUG(2,("Got a positive name query response from %s",
- - inet_ntoa(lastip)));
- - DEBUG(2,(" (%s)\n",inet_ntoa(*ip)));
- - found=True; retries=0;
- - continue;
- - } else {
- - /* some other sort of response, yuck */
- - DEBUG(2,("Unknown response\n"));
- - continue;
- - }
- - } else {
- - if (fn) fn(inbuf);
- - }
- - }
- - }
- + announce_request(PrimaryGroup);
-
- - return(found);
- + needannounce = True;
- }
-
- -/****************************************************************************
- -do a netbios name status to a host
- -****************************************************************************/
- -static BOOL name_status(char *name,int type,struct in_addr to_ip,void (*fn)(),
- - char *master)
- +
- +/*******************************************************************
- + unbecome the master browser
- + ******************************************************************/
- +static void become_nonmaster(void)
- {
- - pstring inbuf,outbuf;
- - static uint16 name_trn_id = 0x4262;
- - char *p;
- - int retries = 3;
- - int retry_time = 5000;
- - struct timeval tval;
- + struct name_record *n;
- + struct nmb_name nn;
-
- - bzero(inbuf,sizeof(inbuf));
- - bzero(outbuf,sizeof(outbuf));
- + DEBUG(2,("Becoming non-master for %s\n",PrimaryGroup));
- +
- + ServerType &= ~SV_TYPE_MASTER_BROWSER;
- + ElectionCriterion &= ~0x4;
-
- - if (!fn)
- - DEBUG(1,("Querying status of name %s\n",name));
- + make_nmb_name(&nn,PrimaryGroup,0x1d,scope);
- + n = find_name(&nn);
- + if (n && n->source == SELF) remove_name(n);
-
- - name_trn_id += getpid() % 100;
- - name_trn_id = (name_trn_id % 10000);
- + make_nmb_name(&nn,MSBROWSE,1,scope);
- + n = find_name(&nn);
- + if (n && n->source == SELF) remove_name(n);
- +}
-
- - RSSVAL(outbuf,0,name_trn_id);
- - CVAL(outbuf,2) = 0;
- - CVAL(outbuf,3) = 0x0;
- - RSSVAL(outbuf,4,1);
- - RSSVAL(outbuf,6,0);
- - RSSVAL(outbuf,8,0);
- - RSSVAL(outbuf,10,0);
- - p = outbuf+12;
- - name_mangle(name,p,type);
- - p += name_len(p);
- - RSSVAL(p,0,0x21);
- - RSSVAL(p,2,0x1);
- - p += 4;
- -
- - DEBUG(fn?3:2,("Sending name status query for %s\n",name));
-
- - show_nmb(outbuf);
- +/*******************************************************************
- + run the election
- + ******************************************************************/
- +static void run_election(void)
- +{
- + time_t t = time(NULL);
- + static time_t lastime = 0;
-
- - GetTimeOfDay(&tval);
- + if (!*PrimaryGroup || !RunningElection) return;
-
- - if (!send_nmb(outbuf,nmb_len(outbuf), &to_ip, 137))
- - return False;
- -
- - while (1)
- - {
- - struct timeval tval2;
- - GetTimeOfDay(&tval2);
- - if (TvalDiff(&tval,&tval2) > retry_time) {
- - if (!retries) break;
- - if (!send_nmb(outbuf,nmb_len(outbuf), &to_ip, 137))
- - return False;
- - GetTimeOfDay(&tval);
- - retries--;
- - }
- -
- - if (receive_nmb(inbuf,90))
- - {
- - int rec_name_trn_id = RSVAL(inbuf,0);
- - int rcode = CVAL(inbuf,3) & 0xF;
- - int response = (CVAL(inbuf,2)>>7);
- - int qdcount = RSVAL(inbuf,4);
- - int ancount = RSVAL(inbuf,6);
- -
- - show_nmb(inbuf);
- -
- - /* is it a positive response to our request? */
- - if (response && (rec_name_trn_id == name_trn_id)) {
- - if (rcode==0 && ancount==1 && qdcount==0) {
- - DEBUG(fn?3:0,("Got a positive node status response from %s\n",
- - inet_ntoa(lastip)));
- - interpret_node_status(inbuf, master);
- - return(True);
- - }
- - return(False);
- - }
- - if (fn) fn(inbuf);
- - }
- - }
- + /* send election packets once a second */
- + if (lastime &&
- + t-lastime <= 0) return;
-
- - DEBUG(0,("No response (this is not unusual)\n"));
- + lastime = t;
-
- - return(False);
- + send_election(PrimaryGroup,ElectionCriterion,t-StartupTime,myname);
- +
- + if (ElectionCount++ < 4) return;
- +
- + /* I won! now what :-) */
- + RunningElection = False;
- + DEBUG(2,(">>> Won election on %s <<<\n",PrimaryGroup));
- + become_master();
- }
-
-
- /****************************************************************************
- -reply to a reg request
- -****************************************************************************/
- -static void reply_name_reg(char *inbuf)
- + construct a host announcement unicast
- + **************************************************************************/
- +static void announce_host(struct domain_record *d,char *my_name,char *comment)
- {
- + time_t t = time(NULL);
- pstring outbuf;
- - int rec_name_trn_id = RSVAL(inbuf,0);
- - char qname[100]="";
- - int ttl;
- - char *p = inbuf;
- - struct in_addr ip;
- - int n=0;
- - int name_type;
- - unsigned char nb_flags;
- - int nm_flags = ((CVAL(inbuf,2) & 0x7) << 4) + (CVAL(inbuf,3)>>4);
- - int bcast = (nm_flags&1);
- - struct in_addr tmpip;
- -
- - bzero(outbuf,sizeof(outbuf));
- + char *p;
- + char *namep;
- + char *stypep;
- + char *commentp;
- +
- + if (needannounce) {
- + /* drop back to a max 3 minute announce - this is to prevent a
- + single lost packet from stuffing things up for too long */
- + d->announce_interval = MIN(d->announce_interval,3*60);
- + d->lastannounce_time = t - (d->announce_interval+1);
- + }
-
- - name_type = name_extract(inbuf,12,qname);
- + /* announce every minute at first then progress to every 12 mins */
- + if (d->lastannounce_time &&
- + (t - d->lastannounce_time) < d->announce_interval)
- + return;
-
- - p += 12;
- - p += name_len(p);
- - p += 4;
- - p += name_len(p);
- - p += 4;
- - ttl = RIVAL(p,0);
- - nb_flags = CVAL(p,6);
- - p += 8;
- - putip((char *)&ip,p);
- -
- - DEBUG(2,("Name registration request for %s (%s) nb_flags=0x%x ntype=%d\n",
- - qname,inet_ntoa(ip),nb_flags,name_type));
- -
- - if ((nb_flags&0x80) == 0 && (name_type != 0x1d)) {
- - if (ttl==0) ttl = NMBD_MAX_TTL;
- - ttl = MIN(ttl,NMBD_MAX_TTL);
- + if (d->announce_interval < 12*60) d->announce_interval += 60;
- + d->lastannounce_time = t;
-
- - n = find_name(qname,name_type,True);
- + DEBUG(2,("Sending announcement to %s for workgroup %s type=%d\n",
- + inet_ntoa(d->bcast_ip),d->name));
-
- - if (n>=0 && names[n].source != REGISTER && names[n].source != DNS)
- - return;
- + if (!*comment) comment = "NoComment";
- + if (!*my_name) my_name = "NoName";
-
- - if (n<0)
- - n = add_name();
- - if (n<0) return;
- -
- - bzero(&names[n],sizeof(names[n]));
- -
- - StrnCpy(names[n].name,qname,15);
- - names[n].type = name_type;
- - names[n].unicast = !dns_serve || is_mynet(ip);
- - names[n].ip = ip;
- - names[n].valid = True;
- - names[n].ttl = ttl;
- - names[n].source = REGISTER;
- - names[n].start_time = time(NULL);
- - DEBUG(2,("Added %s with ttl %d as (%s) (uni=%s)\n",
- - qname,names[n].ttl,inet_ntoa(ip),BOOLSTR(names[n].unicast)));
- - }
- + if (strlen(comment) > 43) comment[43] = 0;
-
- - if (bcast) return;
- + bzero(outbuf,sizeof(outbuf));
- + CVAL(outbuf,0) = 1; /* host announce */
- + p = outbuf+1;
-
- - /* Send a POSITIVE NAME REGISTRATION RESPONSE */
- - RSSVAL(outbuf,0,rec_name_trn_id);
- - CVAL(outbuf,2) = (1<<7) | (5<<3) | 5;
- - CVAL(outbuf,3) = (1<<7);
- - RSSVAL(outbuf,4,0);
- - RSSVAL(outbuf,6,1);
- - RSSVAL(outbuf,8,0);
- - RSSVAL(outbuf,10,0);
- - p = outbuf+12;
- - strcpy(p,inbuf+12);
- - p += name_len(p);
- - RSSVAL(p,0,0x20);
- - RSSVAL(p,2,0x1);
- - /* we want them to refresh in case we die */
- - if (!ttl) ttl = 15*60;
- - ttl = MIN(ttl,15*60);
- - RSIVAL(p,4,ttl);
- -
- - RSSVAL(p,8,6);
- - RSSVAL(p,10,nb_flags);
- - p += 12;
- - putip(p,&ip);
- - p += 4;
- -
- - DEBUG(2,("Sending a positive registration response\n"));
- - if (DEBUGLEVEL > 2)
- - show_nmb(outbuf);
- -
- - tmpip = lastip;
- - num_good_sends++;
- - send_nmb(outbuf,PTR_DIFF(p,outbuf),&tmpip,lastport>0?lastport:137);
- + CVAL(p,0) = updatecount;
- + SIVAL(p,1,d->announce_interval*1000); /* ms - despite the spec */
- + namep = p+5;
- + StrnCpy(p+5,my_name,16);
- + strupper(p+5);
- + CVAL(p,21) = 2; /* major version */
- + CVAL(p,22) = 0; /* minor version */
- + stypep = p+23;
- + SIVAL(p,23,ServerType);
- + SSVAL(p,27,0xaa55); /* browse signature */
- + SSVAL(p,29,1); /* browse version */
- + commentp = p+31;
- + strcpy(p+31,comment);
- + p += 31;
- + p = skip_string(p,1);
- +
- + send_udp_dgram(ClientDGRAM,outbuf,PTR_DIFF(p,outbuf),
- + my_name,d->name,0,0x1d,d->bcast_ip,myip);
- +
- + /* if I'm the master then I also need to do a local master and
- + domain announcement */
- +
- + if (AM_MASTER &&
- + strequal(d->name,PrimaryGroup) &&
- + ip_equal(bcast_ip,d->bcast_ip)) {
- +
- + /* do master announcements as well */
- +
- + CVAL(outbuf,0) = 15; /* local master announce */
- + send_udp_dgram(ClientDGRAM,outbuf,PTR_DIFF(p,outbuf),
- + my_name,PrimaryGroup,0,0x1e,d->bcast_ip,myip);
- +
- + CVAL(outbuf,0) = 12; /* domain announce */
- + StrnCpy(namep,PrimaryGroup,15);
- + strupper(namep);
- + StrnCpy(commentp,myname,15);
- + strupper(commentp);
- + SIVAL(stypep,0,(unsigned)0x80000000);
- + p = commentp + strlen(commentp) + 1;
-
- - return;
- + send_udp_dgram(ClientDGRAM,outbuf,PTR_DIFF(p,outbuf),
- + my_name,MSBROWSE,0,1,d->bcast_ip,myip);
- + }
- }
-
- +
- /****************************************************************************
- -reply to a name release
- -****************************************************************************/
- -static void reply_name_release(char *inbuf)
- + send a announce request to the local net
- + **************************************************************************/
- +static void announce_request(char *group)
- {
- pstring outbuf;
- - int rec_name_trn_id = RSVAL(inbuf,0);
- - char qname[100]="";
- - char *p = inbuf;
- - struct in_addr ip;
- - int n=0;
- - int name_type;
- - unsigned char nb_flags;
- - struct in_addr tmpip;
- - BOOL release_ok=False;
- - int reason=5;
- + char *p;
-
- + DEBUG(2,("Sending announce request to %s for workgroup %s\n",
- + inet_ntoa(bcast_ip),group));
-
- bzero(outbuf,sizeof(outbuf));
- -
- - name_type = name_extract(inbuf,12,qname);
- + p = outbuf;
- + CVAL(p,0) = 2; /* announce request */
- + p++;
-
- - p += 12;
- - p += name_len(p);
- - p += 4;
- - p += name_len(p);
- - p += 4;
- - nb_flags = CVAL(p,6);
- - p += 8;
- - putip((char *)&ip,p);
- -
- - DEBUG(2,("Name release request for %s (%s) nb_flags=0x%x ntype=%d\n",
- - qname,inet_ntoa(ip),nb_flags,name_type));
- -
- - n = find_name(qname,name_type,True);
- - if (n>=0 && names[n].source == REGISTER &&
- - !memcmp((char *)&ip,(char *)&names[n].ip,sizeof(ip))) {
- - release_ok = True;
- - names[n].valid = False;
- - }
- -
- - /* Send a POSITIVE NAME RELEASE RESPONSE */
- - RSSVAL(outbuf,0,rec_name_trn_id);
- - CVAL(outbuf,2) = (1<<7) | (6<<3) | 4;
- - CVAL(outbuf,3) = release_ok?0:reason;
- - RSSVAL(outbuf,4,0);
- - RSSVAL(outbuf,6,1);
- - RSSVAL(outbuf,8,0);
- - RSSVAL(outbuf,10,0);
- - p = outbuf+12;
- - strcpy(p,inbuf+12);
- - p += name_len(p);
- - RSSVAL(p,0,0x20);
- - RSSVAL(p,2,0x1);
- - RSIVAL(p,4,0); /* ttl */
- - RSSVAL(p,8,6);
- - RSSVAL(p,10,nb_flags);
- - p += 12;
- - putip(p,&ip);
- - p += 4;
- -
- - DEBUG(2,("Sending a %s name release response\n",release_ok?"positive":"negative"));
- - if (DEBUGLEVEL > 2)
- - show_nmb(outbuf);
- -
- - tmpip = lastip;
- - num_good_sends++;
- - send_nmb(outbuf,PTR_DIFF(p,outbuf),&tmpip,lastport>0?lastport:137);
- + CVAL(p,0) = 0; /* flags?? */
- + p++;
- + StrnCpy(p,myname,16);
- + strupper(p);
- + p = skip_string(p,1);
-
- - return;
- + send_udp_dgram(ClientDGRAM,outbuf,PTR_DIFF(p,outbuf),
- + myname,group,0,0,bcast_ip,myip);
- }
-
-
- -/****************************************************************************
- -reply to a name status query
- -****************************************************************************/
- -static void reply_name_status(char *inbuf)
- -{
- - pstring outbuf;
- - fstring qname;
- - int rec_name_trn_id = RSVAL(inbuf,0);
- - char *p = inbuf;
- - struct in_addr tmpip;
- - int i;
- - int count=0;
- - int name_type;
- - BOOL wildcard = False;
- -
- - bzero(outbuf,sizeof(outbuf));
- -
- - name_type = name_extract(inbuf,12,qname);
- - wildcard = (qname[0]=='*');
- +/*******************************************************************
- + am I listening on a name. Should check name_type as well
-
- - DEBUG(2,("(%s) status query on name (%s)\n",inet_ntoa(lastip), qname));
- + This is primarily used to prevent us gathering server lists from
- + other workgroups we aren't a part of
- + ******************************************************************/
- +static BOOL listening(struct nmb_name *n)
- +{
- + if (!strequal(n->scope,scope)) return(False);
- +
- + if (strequal(n->name,myname) ||
- + strequal(n->name,PrimaryGroup) ||
- + strequal(n->name,MSBROWSE))
- + return(True);
-
- - if (!wildcard) {
- - i = find_name(qname,name_type,False);
- + return(False);
- +}
-
- - if (i < 0)
- - return;
- - if (names[i].source != SELF && names[i].source != LMHOSTS)
- - return;
- - }
-
- - /* Send a POSITIVE NAME STATUS RESPONSE */
- - RSSVAL(outbuf,0,rec_name_trn_id);
- - CVAL(outbuf,2) = (1<<7) | (1<<2);
- - CVAL(outbuf,3) = 0;
- - RSSVAL(outbuf,4,0);
- - RSSVAL(outbuf,6,1);
- - RSSVAL(outbuf,8,0);
- - RSSVAL(outbuf,10,0);
- - p = outbuf+12;
- - strcpy(p,inbuf+12);
- - p += name_len(p);
- - RSSVAL(p,0,0x21);
- - RSSVAL(p,2,0x1);
- - RSIVAL(p,4,0);
- - RSSVAL(p,8,6);
- - p += 10;
- -
- - for (i=0;i<num_names;i++)
- - if (names[i].valid) count++;
- - count = MIN(count,(512 - (46 + 1 + PTR_DIFF(p,outbuf)))/18);
- +/*******************************************************************
- + process a domain announcement frame
-
- - SCVAL(p,0,count);
- - p++;
- + Announce frames come in 3 types. Servers send host announcements
- + (command=1) to let the master browswer know they are
- + available. Master browsers send local master announcements
- + (command=15) to let other masters and backups that they are the
- + master. They also send domain announcements (command=12) to register
- + the domain
- +
- + The comment field of domain announcements contains the master
- + browser name. The servertype is used by NetServerEnum to select
- + resources. We just have to pass it to smbd (via browser.dat) and let
- + the client choose using bit masks.
- + ******************************************************************/
- +static void process_announce(struct packet_struct *p,int command,char *buf)
- +{
- + struct dgram_packet *dgram = &p->packet.dgram;
- + int update_count = CVAL(buf,0);
- + int ttl = IVAL(buf,1)/1000;
- + char *name = buf+5;
- + int major=CVAL(buf,21);
- + int minor=CVAL(buf,22);
- + uint32 servertype = IVAL(buf,23);
- + char *comment = buf+31;
- +
- + name[15] = 0;
- + comment[43] = 0;
- +
- + DEBUG(3,("Announce(%d) %s count=%d ttl=%d OS=(%d,%d) type=%08x comment=%s\n",
- + command,name,update_count,ttl,major,minor,
- + servertype,comment));
-
- - for (i=0;i<num_names && count>0;i++)
- - if (names[i].valid)
- - {
- - bzero(p,18);
- - strcpy(p,names[i].name);
- - strupper(p);
- - p[15] = names[i].type;
- - p += 16;
- - p[0] = 0x4; /* active */
- - if (strequal(names[i].name,myname)) p[0] |= 0x2; /* permanent */
- - if (ISGROUP(i)) p[0] |= 0x80; /* group */
- - p += 2;
- - count--;
- - }
- + if (strequal(dgram->source_name.name,myname)) return;
-
- - bzero(p,46);
- - putip(p,(char *)&myip);
- - SIVAL(p,20,num_good_sends);
- - SIVAL(p,24,num_good_receives);
- -
- - p += 46;
- -
- - tmpip = lastip;
- - num_good_sends++;
- - send_nmb(outbuf,PTR_DIFF(p,outbuf),&tmpip,lastport>0?lastport:137);
- + if (!listening(&dgram->dest_name)) return;
-
- - return;
- + /* add them to our browse list */
- + add_server_entry(name,servertype,ttl,comment);
- }
-
-
- -/****************************************************************************
- -reply to a name query
- -****************************************************************************/
- -static void reply_name_query(char *inbuf)
- -{
- - pstring outbuf;
- - int rec_name_trn_id = RSVAL(inbuf,0);
- - char qname[100]="";
- - char *p = inbuf;
- - unsigned char nb_flags = 0;
- - int nm_flags = ((CVAL(inbuf,2) & 0x7) << 4) + (CVAL(inbuf,3)>>4);
- - struct in_addr tmpip;
- - struct in_addr retip;
- - int i=-1;
- - BOOL broadcast = ((nm_flags&1) != 0);
- - int name_type;
- - int qtype;
- - BOOL wildcard=False;
- +/*******************************************************************
- + process a backup list request
-
- - bzero(outbuf,sizeof(outbuf));
- + A client send a backup list request to ask for a list of servers on
- + the net that maintain server lists for a domain. A server is then
- + chosen from this list to send NetServerEnum commands to to list
- + available servers.
-
- - name_type = name_extract(inbuf,12,qname);
- + Currently samba only sends back one name in the backup list, its
- + wn. For larger nets we'll have to add backups and send "become
- + backup" requests occasionally.
- + ******************************************************************/
- +static void process_backup_list(struct packet_struct *p,char *buf)
- +{
- + struct dgram_packet *dgram = &p->packet.dgram;
- + int count = CVAL(buf,0);
- + int token = IVAL(buf,1);
- +
- + DEBUG(3,("Backup request to %s token=%d\n",
- + namestr(&dgram->dest_name),
- + token));
-
- - wildcard = (qname[0] == '*');
- + if (strequal(dgram->source_name.name,myname)) return;
-
- - qtype = RSVAL(inbuf+12+name_len(inbuf+12),0);
- + if (count <= 0) return;
-
- - if (qtype == 0x21) {
- - reply_name_status(inbuf);
- + if (!AM_MASTER ||
- + !strequal(PrimaryGroup,dgram->dest_name.name))
- return;
- - }
-
- - if (qtype != 0x20)
- - return;
- + if (!listening(&dgram->dest_name)) return;
-
- - DEBUG(2,("(%s) querying name (%s)(%d) (%s)",
- - inet_ntoa(lastip), qname, name_type,
- - broadcast?"BROADCAST":"UNICAST"));
- + send_backup_list(myname,token,
- + &dgram->source_name,
- + p->ip);
- +}
-
- - if (!wildcard) {
- - i = find_name(qname,name_type,False);
-
- - if (i < 0)
- - i = find_name(qname,name_type,True);
- -
- - if (i >= 0)
- - {
- - if (broadcast && (names[i].unicast || names[i].source == REGISTER)) {
- - DEBUG(2,(" - broadcast. No reply\n"));
- - return;
- - }
- +/*******************************************************************
- + work out if I win an election
- + ******************************************************************/
- +static BOOL win_election(int version,uint32 criterion,int timeup,char *name)
- +{
- + time_t t = time(NULL);
- + uint32 mycriterion;
- + if (version > ELECTION_VERSION) return(False);
- + if (version < ELECTION_VERSION) return(True);
-
- - if (ISGROUP(i)) {
- - DEBUG(2,(" - group name. No reply\n"));
- - return;
- - }
- + mycriterion = ElectionCriterion;
-
- - retip = names[i].ip;
- - DEBUG(2,(" sending positive reply\n"));
- - }
- - else
- - {
- - if ((name_type!=0 && name_type!=0x3 && name_type!=0x20) ||
- - (broadcast && !dns_serve))
- - {
- - DEBUG(2,("\n"));
- - return;
- - }
- - else
- - /* try a DNS query to get the IP */
- - {
- - struct hostent *hp;
- - pstring hname;
- -
- - StrnCpy(hname,qname,15);
- - trim_string(hname," "," ");
- - trim_string(hname,".",".");
- - p = strchr(hname,' ');
- - if (p) *p = 0;
- -
- - if ((hp = Get_Hostbyname(hname)) == 0)
- - {
- - DEBUG(2,(": unknown name sending no reply\n"));
- - return;
- - }
- -
- - putip((char *)&retip,(char *)hp->h_addr);
- -
- - if (broadcast && is_mynet(retip)) {
- - DEBUG(2,(" on same subnet (%s), no reply\n",inet_ntoa(retip)));
- - return;
- - }
- - i = find_name(qname,name_type,True);
- - if (i < 0) {
- - if ((i=add_name())>=0) {
- - StrnCpy(names[i].name,qname,15);
- - names[i].type = name_type;
- - names[i].unicast = is_mynet(retip);
- - names[i].ip = retip;
- - names[i].valid = True;
- - names[i].ttl = 120; /* give it two minutes */
- - names[i].start_time = time(NULL);
- - names[i].source = DNS;
- - }
- - }
- - }
- - DEBUG(2,(" sending positive reply (%s)\n",inet_ntoa(retip)));
- - }
- - } else {
- - retip = myip;
- - }
- -
- - /* Send a POSITIVE NAME QUERY RESPONSE */
- - RSSVAL(outbuf,0,rec_name_trn_id);
- - CVAL(outbuf,2) = (1<<7) | 0x5;
- - CVAL(outbuf,3) = 0;
- - RSSVAL(outbuf,4,0);
- - RSSVAL(outbuf,6,1);
- - RSSVAL(outbuf,8,0);
- - RSSVAL(outbuf,10,0);
- - p = outbuf+12;
- - strcpy(p,inbuf+12);
- - p += name_len(p);
- - RSSVAL(p,0,0x20);
- - RSSVAL(p,2,0x1);
- - RSIVAL(p,4,0); /* my ttl ? */
- - RSSVAL(p,8,6);
- - CVAL(p,10) = nb_flags;
- - CVAL(p,11) = 0;
- - p += 12;
- - putip(p,(char *)&retip);
- - p += 4;
- -
- - show_nmb(outbuf);
- -
- - tmpip = lastip;
- - num_good_sends++;
- - send_nmb(outbuf,nmb_len(outbuf),&tmpip,lastport>0?lastport:137);
- + if (criterion > mycriterion) return(False);
- + if (criterion < mycriterion) return(True);
-
- - return;
- + if (timeup > (t - StartupTime)) return(False);
- + if (timeup < (t - StartupTime)) return(True);
- +
- + if (strcasecmp(myname,name) > 0) return(False);
- +
- + return(True);
- }
-
-
- +/*******************************************************************
- + process a election packet
-
- -/****************************************************************************
- - construct a reply to the incoming packet
- -****************************************************************************/
- -void construct_reply(char *inbuf)
- + An election dynamically decides who will be the master.
- + ******************************************************************/
- +static void process_election(struct packet_struct *p,char *buf)
- {
- - int opcode = CVAL(inbuf,2) >> 3;
- - int nm_flags = ((CVAL(inbuf,2) & 0x7) << 4) + (CVAL(inbuf,3)>>4);
- - int rcode = CVAL(inbuf,3) & 0xF;
- - int bcast = (nm_flags&1);
- - int response = (CVAL(inbuf,2)>>7);
- - int qdcount = RSVAL(inbuf,4);
- - int arcount = RSVAL(inbuf,10);
- + struct dgram_packet *dgram = &p->packet.dgram;
- + int version = CVAL(buf,0);
- + uint32 criterion = IVAL(buf,1);
- + int timeup = IVAL(buf,5)/1000;
- + char *name = buf+13;
-
- - /* if this is a response then ignore it */
- - if (response || rcode) return;
- + name[15] = 0;
-
- - if (!bcast && opcode == 0x5 && qdcount==1 && arcount==1)
- - {
- - reply_name_reg(inbuf);
- - return;
- - }
- + DEBUG(3,("Election request from %s vers=%d criterion=%08x timeup=%d\n",
- + name,version,criterion,timeup));
-
- - if (opcode == 0 && qdcount==1)
- - {
- - reply_name_query(inbuf);
- - return;
- - }
- + if (strequal(dgram->source_name.name,myname)) return;
-
- - if (!bcast && opcode == 6 && qdcount==1 && arcount==1)
- - {
- - reply_name_release(inbuf);
- - return;
- - }
- + if (!listening(&dgram->dest_name)) return;
-
- - if (!bcast && ((opcode == 8) || (opcode == 9)) && qdcount==1 && arcount==1)
- - {
- - reply_name_reg(inbuf);
- - return;
- + if (win_election(version,criterion,timeup,name)) {
- + if (!RunningElection) {
- + needelection = True;
- + ElectionCount=0;
- + }
- + } else {
- + needelection = False;
- + if (RunningElection) {
- + RunningElection = False;
- + DEBUG(3,(">>> Lost election on %s <<<\n",PrimaryGroup));
- +
- + /* if we are the master then remove our masterly names */
- + if (AM_MASTER)
- + become_nonmaster();
- }
- + }
- }
-
-
- -/****************************************************************************
- -construct a host announcement unicast
- -****************************************************************************/
- -static BOOL send_udp_138(char *buf,int len,
- - char *srcname,char *dstname,
- - int src_type,int dest_type,
- - struct in_addr dest_ip)
- +/*******************************************************************
- + process a announcement request
- +
- + clients send these when they want everyone to send an announcement
- + immediately. This can cause quite a storm of packets!
- + ******************************************************************/
- +static void process_announce_request(struct packet_struct *p,char *buf)
- {
- - pstring outbuf;
- - char *p,*p2;
- - static int id=0;
- - char tmp[4];
- - struct sockaddr_in sock_out;
- + struct dgram_packet *dgram = &p->packet.dgram;
- + int flags = CVAL(buf,0);
- + char *name = buf+1;
-
- - bzero(outbuf,sizeof(outbuf));
- - RSSVAL(outbuf,0,0x1102); /* what is this? */
- - RSSVAL(outbuf,2,++id);
- - putip(outbuf+4,(void *)&myip);
- - RSSVAL(outbuf,8,138);
- - RSSVAL(outbuf,12,0);
- - p = outbuf + 14;
- - p += name_mangle(srcname,p,src_type);
- - p += name_mangle(dstname,p,dest_type);
- -
- - /* now setup the smb part */
- - p -= 4;
- - memcpy(tmp,p,4);
- - set_message(p,17,17 + len,True);
- - memcpy(p,tmp,4);
- -
- - CVAL(p,smb_com) = SMBtrans;
- - SSVAL(p,smb_vwv1,len);
- - SSVAL(p,smb_vwv11,len);
- - SSVAL(p,smb_vwv12,86);
- - SSVAL(p,smb_vwv13,3);
- - SSVAL(p,smb_vwv14,1);
- - SSVAL(p,smb_vwv15,1);
- - SSVAL(p,smb_vwv16,2);
- - p2 = smb_buf(p);
- - strcpy(p2,"\\MAILSLOT\\BROWSE");
- - p2 = skip_string(p2,1);
- -
- - memcpy(p2,buf,len);
- - p2 += len;
- -
- - len = PTR_DIFF(p2,outbuf);
- - RSSVAL(outbuf,10,len);
- -
- -
- - /* set the address and port */
- - bzero((char *)&sock_out,sizeof(sock_out));
- - putip((char *)&sock_out.sin_addr,(char *)&dest_ip);
- - sock_out.sin_port = htons(138);
- - sock_out.sin_family = AF_INET;
- -
- - /* log the packet */
- - log_out(outbuf,len);
- -
- - /* send it */
- - if (sendto(Client138,outbuf,len,0,
- - (struct sockaddr *)&sock_out,sizeof(sock_out)) < 0) {
- - DEBUG(3,("Sendto failed errno=%d (%s)\n",errno,strerror(errno)));
- - return(False);
- - } else {
- - num_good_sends++;
- - }
- - return(True);
- + name[15] = 0;
- +
- + DEBUG(3,("Announce request from %s flags=0x%X\n",name,flags));
- +
- + if (strequal(dgram->source_name.name,myname)) return;
- +
- + needannounce = True;
- }
-
- +
- /****************************************************************************
- -construct a host announcement unicast
- +process a browse frame
- ****************************************************************************/
- -static void announce_host(int i,char *my_name,char *Comment)
- +static void process_browse_packet(struct packet_struct *p,char *buf,int len)
- {
- - static int announce_interval = 1;
- - char *group = names[i].name;
- - struct in_addr dest_ip = names[i].ip;
- - pstring outbuf;
- - char *p;
- + int command = CVAL(buf,0);
- + switch (command)
- + {
- + case 1: /* host announce */
- + case 12: /* domain announce */
- + case 15: /* local master announce */
- + process_announce(p,command,buf+1);
- + break;
-
- - names[i].count++;
- + case 2: /* announce request */
- + process_announce_request(p,buf+1);
- + break;
-
- - if ((names[i].count % announce_interval) != 0) return;
- + case 8: /* election */
- + process_election(p,buf+1);
- + break;
-
- - if (announce_interval < 2) announce_interval++;
- + case 9: /* get backup list */
- + process_backup_list(p,buf+1);
- + break;
- + }
- +}
-
- - DEBUG(2,("Sending host announcement to %s for group %s\n",
- - inet_ntoa(dest_ip),group));
-
- - if (!*Comment) Comment = "NoComment";
- - if (!*my_name) my_name = "NoName";
- - if (!*group) group = "NoGroup";
- +/****************************************************************************
- +process udp 138 datagrams
- +****************************************************************************/
- +static void process_dgram(struct packet_struct *p)
- +{
- + char *buf;
- + char *buf2;
- + int len;
- + struct dgram_packet *dgram = &p->packet.dgram;
-
- - if (strlen(Comment) > 47) Comment[47] = 0;
- + if (dgram->header.msg_type != 0x10 &&
- + dgram->header.msg_type != 0x11 &&
- + dgram->header.msg_type != 0x12) {
- + /* don't process error packets etc yet */
- + return;
- + }
-
- - bzero(outbuf,sizeof(outbuf));
- - p = outbuf;
- - CVAL(p,0) = 1; /* host announce */
- - SSVAL(p,1,0x6006); /* update count?? */
- - CVAL(p,3) = 0xEA; /* res1 */
- - SSVAL(p,4,announce_interval);
- - p += 6;
- - StrnCpy(p,my_name,16);
- - strupper(p);
- - p += 16;
- - CVAL(p,0) = 1; /* major version (was 1) */
- - CVAL(p,1) = 0x33; /* minor version (was 51) */
- - SIVAL(p,2,0xB03); /* server and w'station + unix + printq + domain member*/
- - SSVAL(p,6,0x30B); /* election version */
- - SSVAL(p,8,0xAA55); /* browse constant */
- - p += 10;
- - strcpy(p,Comment);
- - p += strlen(p)+1;
- + buf = &dgram->data[0];
- + buf -= 4; /* XXXX for the pseudo tcp length -
- + someday I need to get rid of this */
-
- - send_udp_138(outbuf,PTR_DIFF(p,outbuf),my_name,group,0,0x1d,dest_ip);
- -}
- + if (CVAL(buf,smb_com) != SMBtrans) return;
-
- + len = SVAL(buf,smb_vwv11);
- + buf2 = smb_base(buf) + SVAL(buf,smb_vwv12);
-
- + DEBUG(3,("datagram from %s to %s for %s of type %d len=%d\n",
- + namestr(&dgram->source_name),namestr(&dgram->dest_name),
- + smb_buf(buf),CVAL(buf2,0),len));
-
- -/****************************************************************************
- -send a name registration packet
- -****************************************************************************/
- -static void send_registration(char *name,int name_type,struct in_addr dest_ip,struct in_addr ip,BOOL refresh,int ttl)
- -{
- - char *p;
- - static int t = 0x176;
- - pstring outbuf;
- - bzero(outbuf,sizeof(outbuf));
- - /* send a registration request */
- - RSSVAL(outbuf,0,t++);
- - if (refresh)
- - CVAL(outbuf,2) = (0<<7) | (9<<3) | 0;
- - else
- - CVAL(outbuf,2) = (0<<7) | (5<<3) | 1;
- -
- - CVAL(outbuf,3) = (1<<4);
- - RSSVAL(outbuf,4,1);
- - RSSVAL(outbuf,6,0);
- - RSSVAL(outbuf,8,0);
- - RSSVAL(outbuf,10,1);
- - p = outbuf+12;
- - name_mangle(name,p,name_type);
- - p += name_len(p);
- - RSSVAL(p,0,0x20);
- - RSSVAL(p,2,0x1);
- - p += 4;
- - RSSVAL(p,0,12);
- - CVAL(p,0) = CVAL(p,0) | 0xC0;
- - p += 2;
- - RSSVAL(p,0,0x20);
- - RSSVAL(p,2,0x1);
- - p += 4;
- - RSIVAL(p,0,ttl);
- -
- - RSSVAL(p,4,6);
- - RSSVAL(p,6,0);
- - p += 8;
- - putip(p,&ip);
- - p += 4;
- -
- - DEBUG(2,("Sending a name registration request\n"));
- - if (DEBUGLEVEL > 2)
- - show_nmb(outbuf);
- + /* only understand browse datagrams */
- + if (!strequal(smb_buf(buf),"\\MAILSLOT\\BROWSE"))
- + return;
-
- - num_good_sends++;
- - send_nmb(outbuf,PTR_DIFF(p,outbuf),&dest_ip,137);
- + if (len <= 0) return;
- + process_browse_packet(p,buf2,len);
- }
-
- /*******************************************************************
- -find a master browser
- -********************************************************************/
- -BOOL find_master(char *name1,struct in_addr ip,struct in_addr *ipout,
- - void (*fn)())
- + find a workgroup using the specified broadcast
- + ******************************************************************/
- +static BOOL find_workgroup(char *name,struct in_addr ip)
- {
- - int type = 0x1d;
- - fstring name;
- + fstring name1;
- BOOL ret;
- - strcpy(name,name1);
- - if (strequal(name,"*")) {
- - strcpy(name,"\001\002__MSBROWSE__\002");
- - type = 1;
- - }
- - ret = name_query(name,type,True,ip,ipout,fn);
- + struct in_addr ipout;
- +
- + strcpy(name1,MSBROWSE);
- +
- + ret = name_query(ClientNMB,name1,0x1,True,False,ip,&ipout,queue_packet);
- if (!ret) return(False);
- - if (type != 1) return(True);
-
- - name_status(name,type,*ipout,fn,name1);
- - return(name1[0] != '*');
- + name_status(ClientNMB,name1,0x1,False,ipout,name,queue_packet);
- +
- + if (name[0] != '*') {
- + DEBUG(2,("Found workgroup %s on broadcast %s\n",name,inet_ntoa(ip)));
- + } else {
- + DEBUG(3,("Failed to find workgroup %s on broadcast %s\n",name,inet_ntoa(ip)));
- + }
- + return(name[0] != '*');
- }
-
- +
- /****************************************************************************
- -process a workgroup announce frame
- -****************************************************************************/
- -static void process_workgroup_announce(char *group,struct in_addr ip)
- + a hook for announce handling - called every minute
- + **************************************************************************/
- +static void do_announcements(void)
- {
- - int i;
- - for (i=0;i<num_names;i++)
- - if (names[i].valid) {
- - if (names[i].name[0] == '*') {
- - StrnCpy(names[i].name,group,15);
- - names[i].master_ip = ip;
- - names[i].found_master = True;
- - names[i].count=0;
- - announce_host(i,myname,comment);
- - return;
- - }
- - if (names[i].isgroup && name_equal(names[i].name,group,0,0)) {
- - int j;
- - for (j=i;j<num_names;j++)
- - if (names[j].valid && names[j].isgroup && names[i].found_master &&
- - name_equal(names[i].name,group,0,0)) return;
- - names[i].master_ip = ip;
- - names[i].found_master = True;
- - names[i].count=0;
- - announce_host(i,myname,comment);
- - return;
- + struct domain_record *d;
- +
- + for (d = domainlist; d; d = d->next) {
- + /* if the ip address is 0 then set to the broadcast */
- + if (zero_ip(d->bcast_ip)) d->bcast_ip = bcast_ip;
- +
- + /* if the workgroup is '*' then find a workgroup to be part of */
- + if (d->name[0] == '*') {
- + if (!find_workgroup(d->name,d->bcast_ip)) continue;
- + add_host_entry(d->name,0x1e,False,0,SELF,
- + *interpret_addr2("255.255.255.255"));
- + if (!*PrimaryGroup && ip_equal(bcast_ip,d->bcast_ip)) {
- + strcpy(PrimaryGroup,d->name);
- + strupper(PrimaryGroup);
- }
- }
- +
- + announce_host(d,myname,ServerComment);
- + }
- +
- + needannounce=False;
- }
-
- +/*******************************************************************
- + check if someone still owns a name
- + ******************************************************************/
- +static BOOL confirm_name(struct name_record *n)
- +{
- + struct in_addr ipout;
- + BOOL ret = name_query(ClientNMB,n->name.name,
- + n->name.name_type,False,
- + False,n->ip,&ipout,queue_packet);
- + return(ret && ip_equal(ipout,n->ip));
- +}
-
- /****************************************************************************
- -process a browse frame
- +reply to a name release
- ****************************************************************************/
- -static void process_browse_packet(char *buf,int len)
- +static void reply_name_release(struct packet_struct *p)
- {
- - char *p;
- - int command = CVAL(buf,0);
- - switch (command) {
- - case 0xc: /* workgroup announcement */
- - {
- - fstring group;
- - p = buf + 6;
- - StrnCpy(group,p,15);
- - DEBUG(2,("Got workgroup announce for %s (%s)\n",
- - group,inet_ntoa(lastip)));
- - process_workgroup_announce(group,lastip);
- - break;
- + struct nmb_packet *nmb = &p->packet.nmb;
- + struct packet_struct p2;
- + struct nmb_packet *nmb2;
- + struct res_rec answer_rec;
- + struct in_addr ip;
- + int rcode=0;
- + int nb_flags = nmb->additional->rdata[0];
- + BOOL bcast = nmb->header.nm_flags.bcast;
- +
- +
- + putip((char *)&ip,&nmb->additional->rdata[2]);
- +
- + {
- + struct name_record *n = find_name(&nmb->question.question_name);
- + if (n && n->unique && n->source == REGISTER &&
- + ip_equal(ip,n->ip)) {
- + remove_name(n); n = NULL;
- }
- +
- + /* XXXX under what conditions should we reject the removal?? */
- }
-
- + DEBUG(3,("Name release on name %s rcode=%d\n",
- + namestr(&nmb->question.question_name),rcode));
- +
- + if (bcast) return;
- +
- + /* Send a NAME RELEASE RESPONSE */
- + p2 = *p;
- + nmb2 = &p2.packet.nmb;
- +
- + nmb2->header.response = True;
- + nmb2->header.nm_flags.bcast = False;
- + nmb2->header.nm_flags.recursion_available = CanRecurse;
- + nmb2->header.nm_flags.trunc = False;
- + nmb2->header.nm_flags.authoritative = True;
- + nmb2->header.qdcount = 0;
- + nmb2->header.ancount = 1;
- + nmb2->header.nscount = 0;
- + nmb2->header.arcount = 0;
- + nmb2->header.rcode = rcode;
- +
- + nmb2->answers = &answer_rec;
- + bzero((char *)nmb2->answers,sizeof(*nmb2->answers));
- +
- + nmb2->answers->rr_name = nmb->question.question_name;
- + nmb2->answers->rr_type = nmb->question.question_type;
- + nmb2->answers->rr_class = nmb->question.question_class;
- + nmb2->answers->ttl = 0;
- + nmb2->answers->rdlength = 6;
- + nmb2->answers->rdata[0] = nb_flags;
- + putip(&nmb2->answers->rdata[2],(char *)&ip);
- +
- + send_packet(&p2);
- }
-
- /****************************************************************************
- -process udp 138 datagrams
- -****************************************************************************/
- -static void process_138(void)
- -{
- - pstring inbuf;
- - int len;
- - while (read_max_udp(Client138,inbuf,sizeof(inbuf),1) > 4) {
- - char *p = inbuf;
- - len = RSVAL(inbuf,10);
- - p += 14;
- - p += name_len(p);
- - p += name_len(p);
- - p -= 4;
- - if (CVAL(p,smb_com) != SMBtrans) continue;
- - if (!strequal(smb_buf(p),"\\MAILSLOT\\BROWSE")) continue;
- - len = SVAL(p,smb_vwv11);
- - p = smb_base(p) + SVAL(p,smb_vwv12);
- - if (len <= 0) continue;
- - process_browse_packet(p,len);
- + reply to a reg request
- + **************************************************************************/
- +static void reply_name_reg(struct packet_struct *p)
- +{
- + struct nmb_packet *nmb = &p->packet.nmb;
- + char *qname = nmb->question.question_name.name;
- + BOOL wildcard = (qname[0] == '*');
- + BOOL bcast = nmb->header.nm_flags.bcast;
- + int ttl = nmb->additional->ttl;
- + int name_type = nmb->question.question_name.name_type;
- + int nb_flags = nmb->additional->rdata[0];
- + struct packet_struct p2;
- + struct nmb_packet *nmb2;
- + struct res_rec answer_rec;
- + struct in_addr ip;
- + BOOL group = (nb_flags&0x80)?True:False;
- + int rcode = 0;
- +
- + if (wildcard) return;
- +
- + putip((char *)&ip,&nmb->additional->rdata[2]);
- +
- + if (group) {
- + /* apparently we should return 255.255.255.255 for group queries (email from MS) */
- + ip = *interpret_addr2("255.255.255.255");
- + }
- +
- + {
- + struct name_record *n = find_name(&nmb->question.question_name);
- +
- + if (n) {
- + if (!group && !ip_equal(ip,n->ip)) {
- + /* check if the previous owner still wants it,
- + if so reject the registration, otherwise change the owner
- + and refresh */
- + if (n->source != REGISTER || confirm_name(n)) {
- + rcode = 6;
- + } else {
- + n->ip = ip;
- + n->death_time = ttl?p->timestamp+ttl*3:0;
- + DEBUG(3,("%s changed owner to %s\n",
- + namestr(&n->name),inet_ntoa(n->ip)));
- + }
- + } else {
- + /* refresh the name */
- + if (n->source != SELF)
- + n->death_time = ttl?p->timestamp + ttl*3:0;
- + }
- + } else {
- + /* add the name to our database */
- + n = add_host_entry(qname,name_type,!group,ttl,REGISTER,ip);
- + }
- }
- +
- + if (bcast) return;
- +
- + DEBUG(3,("Name registration for name %s at %s rcode=%d\n",
- + namestr(&nmb->question.question_name),
- + inet_ntoa(ip),rcode));
- +
- + /* Send a NAME REGISTRATION RESPONSE */
- + /* a lot of fields get copied from the query. This gives us the IP
- + and port the reply will be sent to etc */
- + p2 = *p;
- + nmb2 = &p2.packet.nmb;
- +
- + nmb2->header.opcode = 5;
- + nmb2->header.response = True;
- + nmb2->header.nm_flags.bcast = False;
- + nmb2->header.nm_flags.recursion_available = CanRecurse;
- + nmb2->header.nm_flags.trunc = False;
- + nmb2->header.nm_flags.authoritative = True;
- + nmb2->header.qdcount = 0;
- + nmb2->header.ancount = 1;
- + nmb2->header.nscount = 0;
- + nmb2->header.arcount = 0;
- + nmb2->header.rcode = rcode;
- +
- + nmb2->answers = &answer_rec;
- + bzero((char *)nmb2->answers,sizeof(*nmb2->answers));
- +
- + nmb2->answers->rr_name = nmb->question.question_name;
- + nmb2->answers->rr_type = nmb->question.question_type;
- + nmb2->answers->rr_class = nmb->question.question_class;
- +
- + nmb2->answers->ttl = ttl;
- + nmb2->answers->rdlength = 6;
- + nmb2->answers->rdata[0] = nb_flags;
- + putip(&nmb2->answers->rdata[2],(char *)&ip);
- +
- + send_packet(&p2);
- }
-
- +
- /****************************************************************************
- -a hook for registration of my own names
- +reply to a name status query
- ****************************************************************************/
- -static void do_registration_hook(void)
- +static void reply_name_status(struct packet_struct *p)
- {
- - static int count = 0;
- - static time_t last_t=0;
- - time_t t = time(NULL);
- -
- - if (last_t && (t-last_t)<REGISTRATION_INTERVAL) return;
- - last_t = t;
- + struct nmb_packet *nmb = &p->packet.nmb;
- + char *qname = nmb->question.question_name.name;
- + BOOL wildcard = (qname[0] == '*');
- + struct packet_struct p2;
- + struct nmb_packet *nmb2;
- + struct res_rec answer_rec;
- + char *buf;
- + int count;
- + int rcode = 0;
- + struct name_record *n = find_name(&nmb->question.question_name);
- +
- + DEBUG(3,("Name status for name %s\n",
- + namestr(&nmb->question.question_name)));
- +
- + if (!wildcard && (!n || n->source != SELF))
- + return;
- +
- + /* Send a POSITIVE NAME STATUS RESPONSE */
- + /* a lot of fields get copied from the query. This gives us the IP
- + and port the reply will be sent to etc */
- + p2 = *p;
- + nmb2 = &p2.packet.nmb;
- +
- + nmb2->header.response = True;
- + nmb2->header.nm_flags.bcast = False;
- + nmb2->header.nm_flags.recursion_available = CanRecurse;
- + nmb2->header.nm_flags.trunc = False;
- + nmb2->header.nm_flags.authoritative = True; /* WfWg ignores
- + non-authoritative answers */
- + nmb2->header.qdcount = 0;
- + nmb2->header.ancount = 1;
- + nmb2->header.nscount = 0;
- + nmb2->header.arcount = 0;
- + nmb2->header.rcode = rcode;
- +
- + nmb2->answers = &answer_rec;
- + bzero((char *)nmb2->answers,sizeof(*nmb2->answers));
- +
- +
- + nmb2->answers->rr_name = nmb->question.question_name;
- + nmb2->answers->rr_type = nmb->question.question_type;
- + nmb2->answers->rr_class = nmb->question.question_class;
- + nmb2->answers->ttl = 0;
- +
- + for (count=0, n = namelist ; n; n = n->next) {
- + if (n->source != SELF) continue;
- + count++;
- + }
- +
- + count = MIN(count,400/18); /* XXXX hack, we should calculate exactly
- + how many will fit */
- +
-
- - send_registration(myname,0x20,bcast_ip,myip,count>0,300000);
- - count++;
- + buf = &nmb2->answers->rdata[0];
- + SCVAL(buf,0,count);
- + buf += 1;
- +
- + for (n = namelist ; n; n = n->next)
- + {
- + if (n->source != SELF) continue;
- +
- + bzero(buf,18);
- + strcpy(buf,n->name.name);
- + strupper(buf);
- + buf[15] = n->name.name_type;
- + buf += 16;
- + buf[0] = 0x4; /* active */
- + if (!n->unique) buf[0] |= 0x80; /* group */
- + buf += 2;
- + count--;
- + }
- +
- + /* XXXXXXX we should fill in more fields of the statistics structure */
- + bzero(buf,46);
- + putip(buf,(char *)&myip);
- + {
- + extern int num_good_sends,num_good_receives;
- + SIVAL(buf,20,num_good_sends);
- + SIVAL(buf,24,num_good_receives);
- + }
- +
- + buf += 46;
- +
- + nmb2->answers->rdlength = PTR_DIFF(buf,&nmb2->answers->rdata[0]);
- +
- + send_packet(&p2);
- }
-
- +
- +
- /****************************************************************************
- -a hook for browsing handling - called every BROWSE_INTERVAL secs
- +reply to a name query
- ****************************************************************************/
- -static void do_browse_hook(void)
- +static void reply_name_query(struct packet_struct *p)
- {
- - static BOOL first = True;
- - int i;
- - static time_t last_t=0;
- - time_t t = time(NULL);
- -
- - if (last_t && (t-last_t)<browse_interval) return;
- - last_t = t;
- + struct nmb_packet *nmb = &p->packet.nmb;
- + char *qname = nmb->question.question_name.name;
- + BOOL wildcard = (qname[0] == '*');
- + BOOL bcast = nmb->header.nm_flags.bcast;
- + struct in_addr retip;
- + int name_type = nmb->question.question_name.name_type;
- + struct packet_struct p2;
- + struct nmb_packet *nmb2;
- + struct res_rec answer_rec;
- + int ttl=0;
- + int rcode=0;
- + BOOL unique = True;
- +
- + DEBUG(3,("Name query for %s from %s (bcast=%s) - ",
- + namestr(&nmb->question.question_name),
- + inet_ntoa(p->ip),
- + BOOLSTR(bcast)));
-
- - for (i=0;i<num_names;i++)
- - {
- - BOOL old_found_master = names[i].found_master;
- + if (wildcard)
- + retip = myip;
-
- - if (!NAMEVALID(i) || !ISGROUP(i)) continue;
- + if (!wildcard) {
- + struct name_record *n = find_name(&nmb->question.question_name);
-
- - if (names[i].found_master) {
- - struct in_addr ip2;
- - announce_host(i,myname,comment);
- -
- - if (!name_query(names[i].name,0x1d,True,
- - names[i].master_ip,
- - &ip2,construct_reply)) {
- - DEBUG(2,("%s Master browser at %s failed to respond\n",
- - timestring(),
- - inet_ntoa(names[i].master_ip)));
- - names[i].found_master = False;
- - } else {
- - names[i].master_ip = ip2;
- - }
- - }
- + if (!n) {
- + struct in_addr ip;
- + unsigned long a;
-
- - if (!names[i].found_master) {
- - struct in_addr ip2;
- - names[i].found_master = find_master(names[i].name,names[i].ip,&ip2,
- - construct_reply);
- -
- - if (names[i].found_master) {
- - names[i].master_ip = ip2;
- - DEBUG(1,("%s New master browser for %s at %s\n",
- - timestring(),
- - names[i].name,inet_ntoa(names[i].master_ip)));
- - names[i].count = 0;
- - announce_host(i,myname,comment);
- - }
- + /* only do DNS lookups if the query is for type 0x20 or type 0x0 */
- + if (name_type != 0x20 && name_type != 0) {
- + DEBUG(3,("not found\n"));
- + return;
- }
-
- - if (!names[i].found_master) {
- - int level = (old_found_master||first)?1:2;
- - DEBUG(level,("%s Failed to find a master browser for %s using %s\n",
- - timestring(),
- - names[i].name,inet_ntoa(names[i].ip)));
- + /* look it up with DNS */
- + a = interpret_addr(qname);
- +
- + if (!a) {
- + /* no luck with DNS. We could possibly recurse here XXXX */
- + /* if this isn't a bcast then we should send a negative reply XXXX */
- + DEBUG(3,("no recursion\n"));
- + return;
- }
- +
- + /* add it to our cache of names. give it 2 hours in the cache */
- + putip((char *)&ip,(char *)&a);
- + n = add_host_entry(qname,name_type,True,2*60*60,DNS,ip);
- +
- + /* failed to add it? yikes! */
- + if (!n) return;
- + }
- +
- + /* don't respond to bcast queries for group names unless we own them */
- + if (bcast && !n->unique && !n->source == SELF) {
- + DEBUG(3,("no bcast replies\n"));
- + return;
- + }
- +
- + /* don't respond to bcast queries for addresses on the same net as the
- + machine doing the querying unless its our IP */
- + if (bcast &&
- + n->source != SELF &&
- + same_net(n->ip,p->ip)) {
- + DEBUG(3,("same net\n"));
- + return;
- }
- - first = False;
- +
- + /* is our entry already dead? */
- + if (n->death_time) {
- + if (n->death_time < p->timestamp) return;
- + ttl = n->death_time - p->timestamp;
- + }
- +
- + retip = n->ip;
- + unique = n->unique;
- + }
- +
- + /* if the IP is 0 then substitute my IP - we should see which one is on the
- + right interface for the caller to do this right XXX */
- + if (zero_ip(retip)) retip = myip;
- +
- + DEBUG(3,("OK %s rcode=%d\n",inet_ntoa(retip),rcode));
- +
- + /* a lot of fields get copied from the query. This gives us the IP
- + and port the reply will be sent to etc */
- + p2 = *p;
- + nmb2 = &p2.packet.nmb;
- +
- + nmb2->header.response = True;
- + nmb2->header.nm_flags.bcast = False;
- + nmb2->header.nm_flags.recursion_available = CanRecurse;
- + nmb2->header.nm_flags.trunc = False;
- + nmb2->header.nm_flags.authoritative = True; /* WfWg ignores
- + non-authoritative answers */
- + nmb2->header.qdcount = 0;
- + nmb2->header.ancount = 1;
- + nmb2->header.nscount = 0;
- + nmb2->header.arcount = 0;
- + nmb2->header.rcode = rcode;
- +
- + nmb2->answers = &answer_rec;
- + bzero((char *)nmb2->answers,sizeof(*nmb2->answers));
- +
- + nmb2->answers->rr_name = nmb->question.question_name;
- + nmb2->answers->rr_type = nmb->question.question_type;
- + nmb2->answers->rr_class = nmb->question.question_class;
- + nmb2->answers->ttl = ttl;
- + nmb2->answers->rdlength = 6;
- + nmb2->answers->rdata[0] = unique?0:0x80;
- + nmb2->answers->rdata[1] = 0;
- + putip(&nmb2->answers->rdata[2],(char *)&retip);
- +
- + send_packet(&p2);
- +}
- +
- +
- +
- +/* the global packet linked-list. incoming entries are added to the
- + end of this list. it is supposed to remain fairly short so we
- + won't bother with an end pointer. */
- +static struct packet_struct *packet_queue = NULL;
- +
- +
- +/*******************************************************************
- + queue a packet into the packet queue
- + ******************************************************************/
- +static void queue_packet(struct packet_struct *packet)
- +{
- + struct packet_struct *p;
- + if (!packet_queue) {
- + packet->prev = NULL;
- + packet->next = NULL;
- + packet_queue = packet;
- + return;
- + }
- +
- + /* find the bottom */
- + for (p=packet_queue;p->next;p=p->next) ;
- +
- + p->next = packet;
- + packet->next = NULL;
- + packet->prev = p;
- }
-
- /****************************************************************************
- - process commands from the client
- -****************************************************************************/
- -void process(void)
- + process a nmb packet
- + ****************************************************************************/
- +static void process_nmb(struct packet_struct *p)
- {
- - pstring inbuf;
- - static int trans_num = 0;
- - int nread;
- + struct nmb_packet *nmb = &p->packet.nmb;
-
- - bzero(inbuf,sizeof(inbuf));
- + /* if this is a response then ignore it */
- + if (nmb->header.response) return;
-
- - while (True)
- + switch (nmb->header.opcode)
- {
- - if (!browse)
- + case 5:
- + case 8:
- + case 9:
- + if (nmb->header.qdcount>0 &&
- + nmb->header.arcount>0) {
- + reply_name_reg(p);
- + return;
- + }
- + break;
- +
- + case 0:
- + if (nmb->header.qdcount>0)
- {
- - if (!(nread = receive_nmb(inbuf,is_daemon?0:idle_timeout)))
- + switch (nmb->question.question_type)
- {
- - if (is_daemon) continue;
- - return;
- + case 0x20:
- + reply_name_query(p);
- + break;
- +
- + case 0x21:
- + reply_name_status(p);
- + break;
- }
- + return;
- }
- - else
- - {
- - fd_set fds;
- - int selrtn;
- - struct timeval timeout;
- + break;
-
- - do_registration_hook();
- + case 6:
- + if (nmb->header.qdcount>0 &&
- + nmb->header.arcount>0) {
- + reply_name_release(p);
- + return;
- + }
- + break;
- + }
-
- - do_browse_hook();
- +}
-
- - process_138();
-
- - FD_ZERO(&fds);
- - FD_SET(Client,&fds);
-
- - timeout.tv_sec = NMBD_SELECT_LOOP;
- - timeout.tv_usec = 0;
- +/*******************************************************************
- + run elements off the packet queue till its empty
- + ******************************************************************/
- +static void run_packet_queue(void)
- +{
- + struct packet_struct *p;
-
- - selrtn = sys_select(&fds,&timeout);
- + while ((p=packet_queue)) {
- + switch (p->packet_type)
- + {
- + case NMB_PACKET:
- + process_nmb(p);
- + break;
-
- - if (!FD_ISSET(Client,&fds))
- - continue;
- + case DGRAM_PACKET:
- + process_dgram(p);
- + break;
- + }
-
- - nread = read_udp_socket(Client, inbuf, sizeof(pstring));
- - if (nread <= 0)
- - continue;
- - num_good_receives++;
- - }
- + packet_queue = packet_queue->next;
- + if (packet_queue) packet_queue->prev = NULL;
- + free_packet(p);
- + }
- +}
-
- - if (nread < 4)
- - continue;
-
- - if (DEBUGLEVEL > 2)
- - show_nmb(inbuf);
- +/****************************************************************************
- + The main select loop, listen for packets and respond
- + ***************************************************************************/
- +void process(void)
- +{
- +
- + while (True)
- + {
- + fd_set fds;
- + int selrtn;
- + struct timeval timeout;
- +
- + if (needelection && *PrimaryGroup && !RunningElection) {
- + DEBUG(3,(">>> Starting election on %s <<<\n",PrimaryGroup));
- + ElectionCount = 0;
- + RunningElection = True;
- + needelection = False;
- + }
- +
- + FD_ZERO(&fds);
- + FD_SET(ClientNMB,&fds);
- + FD_SET(ClientDGRAM,&fds);
- + /* during elections we need to send election packets at one
- + second intervals */
- + timeout.tv_sec = RunningElection?1:NMBD_SELECT_LOOP;
- + timeout.tv_usec = 0;
- +
- + selrtn = sys_select(&fds,&timeout);
- +
- + if (FD_ISSET(ClientNMB,&fds)) {
- + struct packet_struct *packet = read_packet(ClientNMB,NMB_PACKET);
- + if (packet) queue_packet(packet);
- + }
- +
- + if (FD_ISSET(ClientDGRAM,&fds)) {
- + struct packet_struct *packet = read_packet(ClientDGRAM,DGRAM_PACKET);
- + if (packet) queue_packet(packet);
- + }
- +
- + if (RunningElection)
- + run_election();
-
- - DEBUG(2,("%s Transaction %d\n",timestring(),trans_num));
- + run_packet_queue();
-
- - construct_reply(inbuf);
- + do_announcements();
-
- - trans_num++;
- + housekeeping();
- }
- }
-
- @@ -1688,27 +1784,59 @@
- }
-
- if (isdaemon)
- - Client = open_socket_in(SOCK_DGRAM, port,*lookup?3:0);
- + ClientNMB = open_socket_in(SOCK_DGRAM, port,0);
- else
- - Client = 0;
- + ClientNMB = 0;
-
- - Client138 = open_socket_in(SOCK_DGRAM,138,3);
- + ClientDGRAM = open_socket_in(SOCK_DGRAM,DGRAM_PORT,3);
-
- - if (Client == -1)
- + if (ClientNMB == -1)
- return(False);
-
- signal(SIGPIPE, SIGNAL_CAST sig_pipe);
-
- - set_socket_options(Client,"SO_BROADCAST");
- - set_socket_options(Client138,"SO_BROADCAST");
- - set_socket_options(Client,user_socket_options);
- -
- + set_socket_options(ClientNMB,"SO_BROADCAST");
- + set_socket_options(ClientDGRAM,"SO_BROADCAST");
-
- DEBUG(3, ("Socket opened.\n"));
- return True;
- }
-
-
- +/*******************************************************************
- + check that a IP, bcast and netmask and consistent. Must be a 1s
- + broadcast
- + ******************************************************************/
- +static BOOL ip_consistent(struct in_addr ip,struct in_addr bcast,
- + struct in_addr nmask)
- +{
- + unsigned long a_ip,a_bcast,a_nmask;
- +
- + a_ip = ntohl(ip.s_addr);
- + a_bcast = ntohl(bcast.s_addr);
- + a_nmask = ntohl(nmask.s_addr);
- +
- + /* check the netmask is sane */
- + if (((a_nmask>>24)&0xFF) != 0xFF) {
- + DEBUG(0,("Insane netmask %s\n",inet_ntoa(nmask)));
- + return(False);
- + }
- +
- + /* check the IP and bcast are on the same net */
- + if ((a_ip&a_nmask) != (a_bcast&a_nmask)) {
- + DEBUG(0,("IP and broadcast are on different nets!\n"));
- + return(False);
- + }
- +
- + /* check the IP and bcast are on the same net */
- + if ((a_bcast|a_nmask) != 0xFFFFFFFF) {
- + DEBUG(0,("Not a ones based broadcast %s\n",inet_ntoa(bcast)));
- + return(False);
- + }
- +
- + return(True);
- +}
- +
- /****************************************************************************
- initialise connect, service and file structs
- ****************************************************************************/
- @@ -1737,11 +1865,14 @@
- Netmask = ip2;
- }
-
- - DEBUG(1,("Using IP %s ",inet_ntoa(myip))); /* core dump reported
- - doing this. Why?? XXXXX */
- + DEBUG(1,("Using IP %s ",inet_ntoa(myip)));
- DEBUG(1,("broadcast %s ",inet_ntoa(bcast_ip)));
- DEBUG(1,("netmask %s\n",inet_ntoa(Netmask)));
-
- + if (!ip_consistent(myip,bcast_ip,Netmask)) {
- + DEBUG(0,("WARNING: The IP address, broadcast and Netmask are not consistent\n"));
- + DEBUG(0,("You are likely to experience problems with this setup!\n"));
- + }
- }
-
- if (! *myname) {
- @@ -1751,9 +1882,12 @@
- if (p) *p = 0;
- }
-
- - add_host_name(myname,0x20,&myip);
- - add_host_name(myname,0x0,&myip);
- - add_host_name(myname,0x3,&myip);
- + if (lp_preferred_master()) {
- + needelection = True;
- + ElectionCriterion |= (1<<3);
- + }
- +
- + ElectionCriterion |= (lp_os_level() << 28);
-
- return True;
- }
- @@ -1768,21 +1902,14 @@
- printf("Usage: %s [-n name] [-B bcast address] [-D] [-p port] [-d debuglevel] [-l log basename]\n",pname);
- printf("Version %s\n",VERSION);
- printf("\t-D become a daemon\n");
- - printf("\t-P passive only. don't respond\n");
- - printf("\t-R only reply to queries, don't actively send claims\n");
- printf("\t-p port listen on the specified port\n");
- printf("\t-d debuglevel set the debuglevel\n");
- printf("\t-l log basename. Basename for log/debug files\n");
- printf("\t-n netbiosname. the netbios name to advertise for this host\n");
- printf("\t-B broadcast address the address to use for broadcasts\n");
- printf("\t-N netmask the netmask to use for subnet determination\n");
- - printf("\t-L name lookup this netbios name then exit\n");
- - printf("\t-S serve queries via DNS if not on the same subnet\n");
- printf("\t-H hosts file load a netbios hosts file\n");
- printf("\t-G group name add a group name to be part of\n");
- - printf("\t-b toggles browsing support (defaults to on)\n");
- - printf("\t-M group name searches for a master browser for the given group\n");
- - printf("\t-T interval sets the browse announcement interval in seconds\n");
- printf("\t-C comment sets the machine comment that appears in browse lists\n");
- printf("\n");
- }
- @@ -1790,16 +1917,21 @@
-
- /****************************************************************************
- main program
- -****************************************************************************/
- + **************************************************************************/
- int main(int argc,char *argv[])
- {
- - int port = 137;
- + int port = NMB_PORT;
- int opt;
- - unsigned int lookup_type = 0;
- extern FILE *dbf;
- extern char *optarg;
-
- - *lookup = *host_file = 0;
- + *host_file = 0;
- +
- +#if 0
- + sleep(10);
- +#endif
- +
- + StartupTime = time(NULL);
-
- TimeInit();
-
- @@ -1822,65 +1954,39 @@
-
- signal(SIGHUP,SIGNAL_CAST sig_hup);
-
- + bcast_ip = *interpret_addr2("0.0.0.0");
- + myip = *interpret_addr2("0.0.0.0");
-
- - while ((opt = getopt (argc, argv, "T:O:M:I:C:bAL:i:B:N:Rn:l:d:Dp:hPSH:G:")) != EOF)
- + while ((opt = getopt (argc, argv, "s:T:I:C:bAi:B:N:Rn:l:d:Dp:hSH:G:")) != EOF)
- switch (opt)
- {
- - case 'T':
- - browse_interval = atoi(optarg);
- - browse_interval = MAX(browse_interval,10);
- - break;
- - case 'O':
- - strcpy(user_socket_options,optarg);
- + case 's':
- + strcpy(servicesf,optarg);
- break;
- case 'C':
- - strcpy(comment,optarg);
- + strcpy(ServerComment,optarg);
- break;
- case 'G':
- - add_group_name(optarg);
- - break;
- - case 'b':
- - browse = !browse;
- - break;
- - case 'A':
- - dns_serve = True;
- + add_domain_entry(optarg,bcast_ip);
- break;
- case 'H':
- strcpy(host_file,optarg);
- break;
- case 'I':
- - {
- - unsigned long a = interpret_addr(optarg);
- - putip((char *)&myip,(char *)&a);
- - got_myip = True;
- - }
- + myip = *interpret_addr2(optarg);
- + got_myip = True;
- break;
- case 'B':
- - {
- - unsigned long a = interpret_addr(optarg);
- - putip((char *)&bcast_ip,(char *)&a);
- - got_bcast = True;
- - }
- + bcast_ip = *interpret_addr2(optarg);
- + got_bcast = True;
- break;
- case 'N':
- - {
- - unsigned long a = interpret_addr(optarg);
- - putip((char *)&Netmask,(char *)&a);
- - got_nmask = True;
- - }
- + Netmask = *interpret_addr2(optarg);
- + got_nmask = True;
- break;
- case 'n':
- strcpy(myname,optarg);
- break;
- - case 'P':
- - {
- - extern BOOL passive;
- - passive = True;
- - }
- - break;
- - case 'S':
- - dns_serve = !dns_serve;
- - break;
- case 'l':
- sprintf(debugf,"%s.nmb",optarg);
- break;
- @@ -1888,18 +1994,6 @@
- strcpy(scope,optarg);
- strupper(scope);
- break;
- - case 'L':
- - strcpy(lookup,optarg);
- - break;
- - case 'M':
- - if (*optarg == '-') {
- - strcpy(lookup,"\01\02__MSBROWSE__\02");
- - lookup_type = 1;
- - } else {
- - strcpy(lookup,optarg);
- - lookup_type = 0x1d;
- - }
- - break;
- case 'D':
- is_daemon = True;
- break;
- @@ -1914,14 +2008,12 @@
- exit(0);
- break;
- default:
- - usage(argv[0]);
- - exit(1);
- + if (!is_a_socket(0))
- + usage(argv[0]);
- + break;
- }
-
-
- - if (*lookup)
- - DEBUGLEVEL++;
- -
- if (DEBUGLEVEL > 10)
- {
- extern FILE *login,*logout;
- @@ -1932,16 +2024,12 @@
- logout = fopen(fname,"w");
- }
-
- - if (*lookup)
- - {
- - if (dbf)
- - fclose(dbf);
- - dbf = stdout;
- - }
- -
- DEBUG(1,("%s netbios nameserver version %s started\n",timestring(),VERSION));
- DEBUG(1,("Copyright Andrew Tridgell 1994\n"));
-
- + if (!reload_services(False))
- + return(-1);
- +
- if (*host_file)
- {
- load_hosts_file(host_file);
- @@ -1950,34 +2038,12 @@
-
- init_structs();
-
- - if (*lookup) {
- - BOOL bcast = True;
- - int retries = 2;
- - char *p = strchr(lookup,'#');
- - struct in_addr ip;
- - if (p) {
- - *p = 0;
- - sscanf(p+1,"%x",&lookup_type);
- - bcast = False;
- - retries = 1;
- - }
- - if (!open_sockets(True,port)) return(1);
- - while (retries--)
- - if (name_query(lookup,lookup_type,bcast,bcast_ip,&ip,NULL)) {
- - printf("%s %s\n",inet_ntoa(ip),lookup);
- - name_status(lookup,lookup_type,ip,NULL,NULL);
- - return(0);
- - }
- - printf("couldn't find name %s\n",lookup);
- - return(0);
- - }
- -
- - if (!*comment)
- - strcpy(comment,"Samba %v");
- - string_sub(comment,"%v",VERSION);
- - string_sub(comment,"%h",myhostname);
- + if (!*ServerComment)
- + strcpy(ServerComment,"Samba %v");
- + string_sub(ServerComment,"%v",VERSION);
- + string_sub(ServerComment,"%h",myhostname);
-
- - check_names();
- + add_my_names();
-
- DEBUG(3,("Checked names\n"));
-
- @@ -1990,6 +2056,7 @@
- is_daemon = True;
- }
-
- +
- if (is_daemon) {
- DEBUG(2,("%s becoming a daemon\n",timestring()));
- become_daemon();
- diff -u -r --new-file last-version/source/nameserv2.c samba-1.9.15/source/nameserv2.c
- --- last-version/source/nameserv2.c Sun Nov 12 21:35:59 1995
- +++ samba-1.9.15/source/nameserv2.c Tue Nov 14 21:40:10 1995
- @@ -82,19 +82,26 @@
- /* here are my election parameters */
-
- /* NTAS uses 2, NT uses 1, WfWg uses 0 */
- -#define OS_LEVEL 3
- -#define PREFERRED_MASTER 1
- #define MAINTAIN_LIST 1
- #define ELECTION_VERSION 1
-
- static BOOL RunningElection = False;
- -static BOOL needelection = True;
- +static BOOL needelection = False;
- static int ElectionCount = 0;
- static int StartupTime =0;
- -static uint32 ElectionCriterion =
- -(OS_LEVEL<<28)|(PREFERRED_MASTER<<3)|(MAINTAIN_LIST<<1)|(ELECTION_VERSION<<8);
- +
- +
- +/* WfWg uses 01040b01 */
- +/* Win95 uses 01041501 */
- +/* NTAS uses ?? */
- +static uint32 ElectionCriterion = (MAINTAIN_LIST<<1)|(ELECTION_VERSION<<8);
- +
- +/* we currently support being the master for just one group. Being the
- + master for more than one group might be tricky as NetServerEnum is
- + often asked for a list without naming the group */
- static fstring PrimaryGroup="";
-
- +#define AM_MASTER (PrimaryGroup[0] && (ServerType & SV_TYPE_MASTER_BROWSER))
-
- #define MSBROWSE "\001\002__MSBROWSE__\002"
-
- @@ -107,8 +114,7 @@
-
- DEBUG(0,("Got SIGHUP (reload not implemented)\n"));
- dump_names();
- - if (!is_daemon)
- - exit(1);
- + reload_services(True);
-
- BlockSignals(False);
- #ifndef DONT_REINSTALL_SIG
- @@ -334,7 +340,7 @@
- n = n2;
- }
-
- - if (ttl) n->death_time = time(NULL)+ttl;
- + if (ttl) n->death_time = time(NULL)+ttl*3;
- n->ip = ip;
- n->unique = unique;
- n->source = source;
- @@ -407,7 +413,7 @@
- StrnCpy(s->name,name,sizeof(s->name)-1);
- StrnCpy(s->comment,comment,sizeof(s->comment)-1);
- s->servertype = servertype;
- - s->death_time = ttl?time(NULL)+ttl:0;
- + s->death_time = ttl?time(NULL)+ttl*3:0;
- strupper(s->name);
- if (s->servertype & SV_TYPE_DOMAIN_ENUM) strupper(s->comment);
-
- @@ -433,6 +439,7 @@
- add_host_entry("__SAMBA__",0x0,True,0,SELF,ip);
- add_host_entry(myname,0x20,True,0,SELF,ip);
- add_host_entry(myname,0x0,True,0,SELF,ip);
- + add_host_entry(myname,0x1f,True,0,SELF,ip); /* used for chat, I think */
- if (!domainlist)
- add_domain_entry(lp_workgroup(),bcast_ip);
- add_server_entry(myname,
- @@ -442,9 +449,48 @@
-
-
- /*******************************************************************
- - delete old names from the namelist
- + write out browse.dat
- ******************************************************************/
- -static void housekeeping(void)
- +static void write_browse_list(void)
- +{
- + struct server_record *s;
- + pstring fname,fnamenew;
- + FILE *f;
- +
- + updatecount++;
- +
- + strcpy(fname,lp_lockdir());
- + trim_string(fname,NULL,"/");
- + strcat(fname,"/");
- + strcat(fname,SERVER_LIST);
- + strcpy(fnamenew,fname);
- + strcat(fnamenew,".");
- +
- + f = fopen(fnamenew,"w");
- +
- + if (!f) {
- + DEBUG(4,("Can't open %s - %s\n",fnamenew,strerror(errno)));
- + return;
- + }
- +
- + for (s=serverlist; s ; s = s->next) {
- + /* don't list domains I don't have a master for */
- + if ((s->servertype & SV_TYPE_DOMAIN_ENUM) && !s->comment[0]) continue;
- +
- + fprintf(f,"\"%s\"\t%08x\t\"%s\"\n",s->name,s->servertype,s->comment);
- + }
- +
- +
- + fclose(f);
- + unlink(fname);
- + rename(fnamenew,fname);
- + DEBUG(3,("Wrote browse list %s\n",fname));
- +}
- +
- +/*******************************************************************
- + expire old names in the namelist and serverlist
- + ******************************************************************/
- +static void expire_names(void)
- {
- static time_t lastrun=0;
- time_t t = time(NULL);
- @@ -453,7 +499,6 @@
- struct server_record *s;
- struct server_record *nexts;
-
- - /* don't run this to often */
- if (!lastrun) lastrun = t;
- if (t < lastrun + 5) return;
- lastrun = t;
- @@ -477,6 +522,7 @@
- for (s = serverlist; s; s = nexts) {
- if (s->death_time && s->death_time < t) {
- DEBUG(3,("Removing dead server %s\n",s->name));
- + updatedlists = True;
- nexts = s->next;
- if (s->prev) s->prev->next = s->next;
- if (s->next) s->next->prev = s->prev;
- @@ -486,44 +532,38 @@
- nexts = s->next;
- }
- }
- -
- -
- - /* write out the browse.dat database for smbd to get */
- - if (!updatedlists) return;
- - updatedlists = False;
- - updatecount++;
- - {
- - pstring fname,fnamenew;
- - FILE *f;
- +}
-
- - strcpy(fname,lp_lockdir());
- - trim_string(fname,NULL,"/");
- - strcat(fname,"/");
- - strcat(fname,SERVER_LIST);
- - strcpy(fnamenew,fname);
- - strcat(fnamenew,".");
-
- - f = fopen(fnamenew,"w");
- +/*******************************************************************
- + delete old names from the namelist
- + ******************************************************************/
- +static void housekeeping(void)
- +{
- + time_t t = time(NULL);
-
- - if (!f) {
- - DEBUG(4,("Can't open %s - %s\n",fnamenew,strerror(errno)));
- - return;
- - }
- + expire_names();
-
- - for (s=serverlist; s ; s = s->next) {
- - /* don't list domains I don't have a master for */
- - if ((s->servertype & SV_TYPE_DOMAIN_ENUM) && !s->comment[0]) continue;
- + /* write out the browse.dat database for smbd to get */
- + if (updatedlists) {
- + write_browse_list();
- + updatedlists = False;
- + }
-
- - fprintf(f,"\"%s\"\t%08x\t\"%s\"\n",s->name,s->servertype,s->comment);
- + {
- + /* occasionally check to see if the master browser is around */
- + static time_t lastrun=0;
- + if (!lastrun) lastrun = t;
- + if (t < lastrun + 5*60) return;
- + lastrun = t;
- +
- + if (!AM_MASTER && *PrimaryGroup &&
- + !name_query(ClientNMB,PrimaryGroup,0x1d,True,False,
- + bcast_ip,NULL,queue_packet)) {
- + DEBUG(2,("Forcing election on %s\n",PrimaryGroup));
- + needelection = True;
- }
- -
- -
- - fclose(f);
- - unlink(fname);
- - rename(fnamenew,fname);
- - DEBUG(3,("Wrote browse list %s\n",fname));
- }
- -
- }
-
-
- @@ -630,11 +670,11 @@
- ******************************************************************/
- static BOOL same_net(struct in_addr ip1,struct in_addr ip2)
- {
- - unsigned int net1,net2,nmask;
- + unsigned long net1,net2,nmask;
-
- - putip((char *)&nmask,(char *)&Netmask);
- - putip((char *)&net1,(char *)&ip1);
- - putip((char *)&net2,(char *)&ip2);
- + nmask = ntohl(Netmask.s_addr);
- + net1 = ntohl(ip1.s_addr);
- + net2 = ntohl(ip2.s_addr);
-
- return((net1 & nmask) == (net2 & nmask));
- }
- @@ -779,11 +819,14 @@
- pstring outbuf;
- char *p;
- char *namep;
- + char *stypep;
- char *commentp;
-
- if (needannounce) {
- - d->announce_interval = 0;
- - d->lastannounce_time = t - 1;
- + /* drop back to a max 3 minute announce - this is to prevent a
- + single lost packet from stuffing things up for too long */
- + d->announce_interval = MIN(d->announce_interval,3*60);
- + d->lastannounce_time = t - (d->announce_interval+1);
- }
-
- /* announce every minute at first then progress to every 12 mins */
- @@ -813,6 +856,7 @@
- strupper(p+5);
- CVAL(p,21) = 2; /* major version */
- CVAL(p,22) = 0; /* minor version */
- + stypep = p+23;
- SIVAL(p,23,ServerType);
- SSVAL(p,27,0xaa55); /* browse signature */
- SSVAL(p,29,1); /* browse version */
- @@ -824,8 +868,10 @@
- send_udp_dgram(ClientDGRAM,outbuf,PTR_DIFF(p,outbuf),
- my_name,d->name,0,0x1d,d->bcast_ip,myip);
-
- - if ((ServerType & SV_TYPE_MASTER_BROWSER) &&
- - *PrimaryGroup &&
- + /* if I'm the master then I also need to do a local master and
- + domain announcement */
- +
- + if (AM_MASTER &&
- strequal(d->name,PrimaryGroup) &&
- ip_equal(bcast_ip,d->bcast_ip)) {
-
- @@ -840,6 +886,7 @@
- strupper(namep);
- StrnCpy(commentp,myname,15);
- strupper(commentp);
- + SIVAL(stypep,0,(unsigned)0x80000000);
- p = commentp + strlen(commentp) + 1;
-
- send_udp_dgram(ClientDGRAM,outbuf,PTR_DIFF(p,outbuf),
- @@ -875,10 +922,39 @@
- }
-
-
- +/*******************************************************************
- + am I listening on a name. Should check name_type as well
- +
- + This is primarily used to prevent us gathering server lists from
- + other workgroups we aren't a part of
- + ******************************************************************/
- +static BOOL listening(struct nmb_name *n)
- +{
- + if (!strequal(n->scope,scope)) return(False);
- +
- + if (strequal(n->name,myname) ||
- + strequal(n->name,PrimaryGroup) ||
- + strequal(n->name,MSBROWSE))
- + return(True);
- +
- + return(False);
- +}
-
-
- /*******************************************************************
- process a domain announcement frame
- +
- + Announce frames come in 3 types. Servers send host announcements
- + (command=1) to let the master browswer know they are
- + available. Master browsers send local master announcements
- + (command=15) to let other masters and backups that they are the
- + master. They also send domain announcements (command=12) to register
- + the domain
- +
- + The comment field of domain announcements contains the master
- + browser name. The servertype is used by NetServerEnum to select
- + resources. We just have to pass it to smbd (via browser.dat) and let
- + the client choose using bit masks.
- ******************************************************************/
- static void process_announce(struct packet_struct *p,int command,char *buf)
- {
- @@ -900,12 +976,24 @@
-
- if (strequal(dgram->source_name.name,myname)) return;
-
- + if (!listening(&dgram->dest_name)) return;
- +
- + /* add them to our browse list */
- add_server_entry(name,servertype,ttl,comment);
- }
-
-
- /*******************************************************************
- process a backup list request
- +
- + A client send a backup list request to ask for a list of servers on
- + the net that maintain server lists for a domain. A server is then
- + chosen from this list to send NetServerEnum commands to to list
- + available servers.
- +
- + Currently samba only sends back one name in the backup list, its
- + wn. For larger nets we'll have to add backups and send "become
- + backup" requests occasionally.
- ******************************************************************/
- static void process_backup_list(struct packet_struct *p,char *buf)
- {
- @@ -921,10 +1009,12 @@
-
- if (count <= 0) return;
-
- - if (!*PrimaryGroup || !(ServerType & SV_TYPE_MASTER_BROWSER) ||
- + if (!AM_MASTER ||
- !strequal(PrimaryGroup,dgram->dest_name.name))
- return;
-
- + if (!listening(&dgram->dest_name)) return;
- +
- send_backup_list(myname,token,
- &dgram->source_name,
- p->ip);
- @@ -957,6 +1047,8 @@
-
- /*******************************************************************
- process a election packet
- +
- + An election dynamically decides who will be the master.
- ******************************************************************/
- static void process_election(struct packet_struct *p,char *buf)
- {
- @@ -972,29 +1064,33 @@
- name,version,criterion,timeup));
-
- if (strequal(dgram->source_name.name,myname)) return;
- - if (!*PrimaryGroup ||
- - !strequal(dgram->dest_name.name,PrimaryGroup)) return;
- +
- + if (!listening(&dgram->dest_name)) return;
-
- if (win_election(version,criterion,timeup,name)) {
- if (!RunningElection) {
- - DEBUG(3,(">>> Starting election on %s <<<\n",PrimaryGroup));
- needelection = True;
- ElectionCount=0;
- }
- } else {
- - RunningElection = False;
- needelection = False;
- - /* if we are the master then remove our masterly name */
- - if (ServerType & SV_TYPE_MASTER_BROWSER) {
- + if (RunningElection) {
- + RunningElection = False;
- DEBUG(3,(">>> Lost election on %s <<<\n",PrimaryGroup));
- - become_nonmaster();
- +
- + /* if we are the master then remove our masterly names */
- + if (AM_MASTER)
- + become_nonmaster();
- }
- }
- -
- }
-
- +
- /*******************************************************************
- process a announcement request
- +
- + clients send these when they want everyone to send an announcement
- + immediately. This can cause quite a storm of packets!
- ******************************************************************/
- static void process_announce_request(struct packet_struct *p,char *buf)
- {
- @@ -1174,7 +1270,6 @@
- DEBUG(3,("Name release on name %s rcode=%d\n",
- namestr(&nmb->question.question_name),rcode));
-
- -
- if (bcast) return;
-
- /* Send a NAME RELEASE RESPONSE */
- @@ -1246,14 +1341,14 @@
- rcode = 6;
- } else {
- n->ip = ip;
- - n->death_time = ttl?p->timestamp+ttl:0;
- + n->death_time = ttl?p->timestamp+ttl*3:0;
- DEBUG(3,("%s changed owner to %s\n",
- namestr(&n->name),inet_ntoa(n->ip)));
- }
- } else {
- /* refresh the name */
- if (n->source != SELF)
- - n->death_time = ttl?p->timestamp + ttl:0;
- + n->death_time = ttl?p->timestamp + ttl*3:0;
- }
- } else {
- /* add the name to our database */
- @@ -1351,7 +1446,7 @@
- nmb2->answers->ttl = 0;
-
- for (count=0, n = namelist ; n; n = n->next) {
- - if (n->source != SELF && n->source != LMHOSTS) continue;
- + if (n->source != SELF) continue;
- count++;
- }
-
- @@ -1365,7 +1460,7 @@
-
- for (n = namelist ; n; n = n->next)
- {
- - if (n->source != SELF && n->source != LMHOSTS) continue;
- + if (n->source != SELF) continue;
-
- bzero(buf,18);
- strcpy(buf,n->name.name);
- @@ -1459,10 +1554,10 @@
- return;
- }
-
- - /* don't respond to bcast queries for addresses on the same net as the machine
- - doing the querying unless its our IP (or something from LMHOSTS) */
- + /* don't respond to bcast queries for addresses on the same net as the
- + machine doing the querying unless its our IP */
- if (bcast &&
- - n->source != SELF && n->source != LMHOSTS &&
- + n->source != SELF &&
- same_net(n->ip,p->ip)) {
- DEBUG(3,("same net\n"));
- return;
- @@ -1479,7 +1574,7 @@
- }
-
- /* if the IP is 0 then substitute my IP - we should see which one is on the
- - right interface for the caller to do this right */
- + right interface for the caller to do this right XXX */
- if (zero_ip(retip)) retip = myip;
-
- DEBUG(3,("OK %s rcode=%d\n",inet_ntoa(retip),rcode));
- @@ -1636,6 +1731,7 @@
- struct timeval timeout;
-
- if (needelection && *PrimaryGroup && !RunningElection) {
- + DEBUG(3,(">>> Starting election on %s <<<\n",PrimaryGroup));
- ElectionCount = 0;
- RunningElection = True;
- needelection = False;
- @@ -1644,6 +1740,8 @@
- FD_ZERO(&fds);
- FD_SET(ClientNMB,&fds);
- FD_SET(ClientDGRAM,&fds);
- + /* during elections we need to send election packets at one
- + second intervals */
- timeout.tv_sec = RunningElection?1:NMBD_SELECT_LOOP;
- timeout.tv_usec = 0;
-
- @@ -1705,6 +1803,40 @@
- }
-
-
- +/*******************************************************************
- + check that a IP, bcast and netmask and consistent. Must be a 1s
- + broadcast
- + ******************************************************************/
- +static BOOL ip_consistent(struct in_addr ip,struct in_addr bcast,
- + struct in_addr nmask)
- +{
- + unsigned long a_ip,a_bcast,a_nmask;
- +
- + a_ip = ntohl(ip.s_addr);
- + a_bcast = ntohl(bcast.s_addr);
- + a_nmask = ntohl(nmask.s_addr);
- +
- + /* check the netmask is sane */
- + if (((a_nmask>>24)&0xFF) != 0xFF) {
- + DEBUG(0,("Insane netmask %s\n",inet_ntoa(nmask)));
- + return(False);
- + }
- +
- + /* check the IP and bcast are on the same net */
- + if ((a_ip&a_nmask) != (a_bcast&a_nmask)) {
- + DEBUG(0,("IP and broadcast are on different nets!\n"));
- + return(False);
- + }
- +
- + /* check the IP and bcast are on the same net */
- + if ((a_bcast|a_nmask) != 0xFFFFFFFF) {
- + DEBUG(0,("Not a ones based broadcast %s\n",inet_ntoa(bcast)));
- + return(False);
- + }
- +
- + return(True);
- +}
- +
- /****************************************************************************
- initialise connect, service and file structs
- ****************************************************************************/
- @@ -1733,11 +1865,14 @@
- Netmask = ip2;
- }
-
- - DEBUG(1,("Using IP %s ",inet_ntoa(myip))); /* core dump reported
- - doing this. Why?? XXXXX */
- + DEBUG(1,("Using IP %s ",inet_ntoa(myip)));
- DEBUG(1,("broadcast %s ",inet_ntoa(bcast_ip)));
- DEBUG(1,("netmask %s\n",inet_ntoa(Netmask)));
-
- + if (!ip_consistent(myip,bcast_ip,Netmask)) {
- + DEBUG(0,("WARNING: The IP address, broadcast and Netmask are not consistent\n"));
- + DEBUG(0,("You are likely to experience problems with this setup!\n"));
- + }
- }
-
- if (! *myname) {
- @@ -1747,6 +1882,13 @@
- if (p) *p = 0;
- }
-
- + if (lp_preferred_master()) {
- + needelection = True;
- + ElectionCriterion |= (1<<3);
- + }
- +
- + ElectionCriterion |= (lp_os_level() << 28);
- +
- return True;
- }
-
- @@ -1866,8 +2008,9 @@
- exit(0);
- break;
- default:
- - usage(argv[0]);
- - exit(1);
- + if (!is_a_socket(0))
- + usage(argv[0]);
- + break;
- }
-
-
- diff -u -r --new-file last-version/source/nmblib.c samba-1.9.15/source/nmblib.c
- --- last-version/source/nmblib.c Sun Nov 12 15:16:26 1995
- +++ samba-1.9.15/source/nmblib.c Tue Nov 14 21:23:08 1995
- @@ -1,7 +1,7 @@
- /*
- Unix SMB/Netbios implementation.
- Version 1.9.
- - NBT netbios routines and daemon - version 2
- + NBT netbios library routines
- Copyright (C) Andrew Tridgell 1994-1995
-
- This program is free software; you can redistribute it and/or modify
- @@ -649,7 +649,9 @@
-
-
- /****************************************************************************
- - do a netbios name status to a host
- + do a netbios name status query on a host
- +
- + the "master" parameter is a hack used for finding workgroups.
- **************************************************************************/
- BOOL name_status(int fd,char *name,int name_type,BOOL recurse,
- struct in_addr to_ip,char *master,void (*fn)())
- @@ -818,7 +820,8 @@
- struct nmb_packet *nmb2 = &p2->packet.nmb;
- if (nmb->header.name_trn_id != nmb2->header.name_trn_id ||
- !nmb2->header.response) {
- - /* its not for us - maybe deal with it later (put it on the queue?) */
- + /* its not for us - maybe deal with it later
- + (put it on the queue?) */
- if (fn)
- fn(p2);
- else
- @@ -836,12 +839,15 @@
- continue;
- }
-
- - putip((char *)ip,&nmb2->answers->rdata[2]);
- - DEBUG(2,("Got a positive name query response from %s",
- - inet_ntoa(p2->ip)));
- - DEBUG(2,(" (%s)\n",inet_ntoa(*ip)));
- + if (ip) {
- + putip((char *)ip,&nmb2->answers->rdata[2]);
- + DEBUG(fn?3:2,("Got a positive name query response from %s",
- + inet_ntoa(p2->ip)));
- + DEBUG(fn?3:2,(" (%s)\n",inet_ntoa(*ip)));
- + }
- found=True; retries=0;
- free_packet(p2);
- + if (fn) break;
- }
- }
-
- @@ -851,6 +857,9 @@
-
- /****************************************************************************
- construct and send a netbios DGRAM
- +
- + Note that this currently sends all answers to port 138. thats the
- + wrong things to do! I should send to the requestors port. XXX
- **************************************************************************/
- BOOL send_udp_dgram(int fd,char *buf,int len,
- char *srcname,char *dstname,
- diff -u -r --new-file last-version/source/reply.c samba-1.9.15/source/reply.c
- --- last-version/source/reply.c Mon Nov 6 16:14:59 1995
- +++ samba-1.9.15/source/reply.c Mon Nov 13 19:30:23 1995
- @@ -707,22 +707,15 @@
-
- /* turn strings of spaces into a . */
- {
- - p = strrchr(mask,' ');
- - if (p)
- + trim_string(mask,NULL," ");
- + if ((p = strrchr(mask,' ')))
- {
- - if (!p[1])
- - {
- - while (*p == ' ') {*p = 0;p--;}
- - }
- - else
- - {
- - fstring ext;
- - strcpy(ext,p+1);
- - *p = 0;
- - trim_string(mask,NULL," ");
- - strcat(mask,".");
- - strcat(mask,ext);
- - }
- + fstring ext;
- + strcpy(ext,p+1);
- + *p = 0;
- + trim_string(mask,NULL," ");
- + strcat(mask,".");
- + strcat(mask,ext);
- }
- }
-
- diff -u -r --new-file last-version/source/server.c samba-1.9.15/source/server.c
- --- last-version/source/server.c Sun Nov 12 13:21:30 1995
- +++ samba-1.9.15/source/server.c Tue Nov 14 23:15:32 1995
- @@ -185,6 +185,11 @@
- if (S_ISDIR(sbuf->st_mode))
- result = aDIR | (result & aRONLY);
-
- +#if LINKS_READ_ONLY
- + if (S_ISLNK(sbuf->st_mode) && S_ISDIR(sbuf->st_mode))
- + result |= aRONLY;
- +#endif
- +
- /* hide files with a name starting with a . */
- if (lp_hide_dot_files(SNUM(cnum)))
- {
- @@ -2725,7 +2730,6 @@
- int reply_lanman1(char *outbuf)
- {
- int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
- - int outsize;
- int secword=0;
- BOOL doencrypt = SMBENCRYPT();
- time_t t = time(NULL);
- @@ -2733,13 +2737,20 @@
- if (lp_security()>=SEC_USER) secword |= 1;
- if (doencrypt) secword |= 2;
-
- - outsize = set_message(outbuf,13,doencrypt?8:0,True);
- + set_message(outbuf,13,doencrypt?8:0,True);
- SSVAL(outbuf,smb_vwv1,secword);
- #ifdef SMB_PASSWD
- /* Create a token value and add it to the outgoing packet. */
- if (doencrypt)
- generate_next_challenge(smb_buf(outbuf));
- #endif
- +
- + Protocol = PROTOCOL_LANMAN1;
- +
- + if (lp_security() == SEC_SERVER && server_cryptkey(outbuf)) {
- + DEBUG(3,("using password server validation\n"));
- + }
- +
- CVAL(outbuf,smb_flg) = 0x81; /* Reply, SMBlockread, SMBwritelock supported */
- SSVAL(outbuf,smb_vwv2,maxxmit);
- SSVAL(outbuf,smb_vwv3,lp_maxmux()); /* maxmux */
- @@ -2751,9 +2762,7 @@
-
- put_dos_date(outbuf,smb_vwv8,t);
-
- - Protocol = PROTOCOL_LANMAN1;
- -
- - return outsize;
- + return (smb_len(outbuf)+4);
- }
-
-
- @@ -2763,7 +2772,6 @@
- int reply_lanman2(char *outbuf)
- {
- int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
- - int outsize;
- int secword=0;
- BOOL doencrypt = SMBENCRYPT();
- time_t t = time(NULL);
- @@ -2771,7 +2779,7 @@
- if (lp_security()>=SEC_USER) secword |= 1;
- if (doencrypt) secword |= 2;
-
- - outsize = set_message(outbuf,13,doencrypt?8:0,True);
- + set_message(outbuf,13,doencrypt?8:0,True);
- SSVAL(outbuf,smb_vwv1,secword);
- #ifdef SMB_PASSWD
- /* Create a token value and add it to the outgoing packet. */
- @@ -2795,7 +2803,7 @@
- SSVAL(outbuf,smb_vwv10, TimeDiff(t)/60);
- put_dos_date(outbuf,smb_vwv8,t);
-
- - return (outsize);
- + return (smb_len(outbuf)+4);
- }
-
- /****************************************************************************
- diff -u -r --new-file last-version/source/smb.h samba-1.9.15/source/smb.h
- --- last-version/source/smb.h Sun Nov 12 13:21:29 1995
- +++ samba-1.9.15/source/smb.h Tue Nov 14 21:55:41 1995
- @@ -767,7 +767,7 @@
- char *smb_trans2_data(char *buf);
- BOOL strequal(char *,char *);
- BOOL strcsequal(char *,char *);
- -BOOL mask_match( char *str, char *regexp, int case_sig, BOOL autoext);
- +BOOL mask_match( char *str, char *regexp, int case_sig, BOOL trans2);
- int dos_mode(int ,char *,struct stat *);
- char *timestring();
- BOOL ip_equal(struct in_addr ip1,struct in_addr ip2);
- diff -u -r --new-file last-version/source/status.c samba-1.9.15/source/status.c
- --- last-version/source/status.c Sun Nov 12 13:08:59 1995
- +++ samba-1.9.15/source/status.c Mon Nov 13 15:53:03 1995
- @@ -30,6 +30,15 @@
- extern int DEBUGLEVEL;
- extern FILE *dbf;
-
- +static pstring Ucrit_username = ""; /* added by OH */
- +int Ucrit_pid[100]; /* Ugly !!! */ /* added by OH */
- +int Ucrit_MaxPid=0; /* added by OH */
- +unsigned int Ucrit_IsActive = 0; /* added by OH */
- +void Ucrit_addUsername(pstring username); /* added by OH */
- +unsigned int Ucrit_checkUsername(pstring username); /* added by OH */
- +void Ucrit_addPid(int pid); /* added by OH */
- +unsigned int Ucrit_checkPid(int pid); /* added by OH */
- +
- int main(int argc, char *argv[])
- {
- FILE *f;
- @@ -42,6 +51,7 @@
- char *s;
- BOOL firstopen=True;
- BOOL processes_only=False;
- + int last_pid=0;
-
- charset_initialise();
-
- @@ -53,7 +63,7 @@
- return(1);
- }
-
- - while ((c = getopt(argc, argv, "pds:")) != EOF) {
- + while ((c = getopt(argc, argv, "pdsu:")) != EOF) {
- switch (c) {
- case 'd':
- verbose = 1;
- @@ -64,13 +74,18 @@
- case 's':
- strcpy(servicesf, optarg);
- break;
- + case 'u': /* added by OH */
- + Ucrit_addUsername(optarg); /* added by OH */
- + break;
- default:
- - fprintf(stderr, "Usage: %s [-p] [-d] [-s configfile]\n", *argv);
- + fprintf(stderr, "Usage: %s [-d] [-p] [-s configfile] [-u username]\n", *argv); /* changed by OH */
- return (-1);
- }
- }
-
- - if (!lp_load(servicesf,True)) {
- +
- +
- + if (!lp_load(servicesf,False)) {
- fprintf(stderr, "Can't load %s - run testparm to debug it\n", servicesf);
- return (-1);
- }
- @@ -97,28 +112,30 @@
-
- if (!processes_only) {
- printf("\nSamba version %s\n",VERSION);
- -
- +
- printf("Service uid gid pid machine\n");
- printf("----------------------------------------------\n");
- }
-
- while (!feof(f))
- {
- - static int last_pid = 0;
- if (fread(&crec,sizeof(crec),1,f) != 1)
- break;
- - if (crec.magic == 0x280267 && process_exists(crec.pid)) {
- + if ( crec.magic == 0x280267 && process_exists(crec.pid)
- + && Ucrit_checkUsername(uidtoname(crec.uid)) /* added by OH */
- + )
- + {
- + Ucrit_addPid(crec.pid); /* added by OH */
- if (processes_only) {
- if (last_pid != crec.pid)
- printf("%d\n",crec.pid);
- last_pid = crec.pid; /* XXXX we can still get repeats, have to
- add a sort at some time */
- }
- - else
- + else
- printf("%-10.10s %-8s %-8s %5d %-8s (%s) %s",
- crec.name,uidtoname(crec.uid),gidtoname(crec.gid),crec.pid,
- - crec.machine,crec.addr,
- - asctime(LocalTime(&crec.start,GMT_TO_LOCAL)));
- + crec.machine,crec.addr,asctime(LocalTime(&crec.start,0)));
- }
- }
- fclose(f);
- @@ -155,9 +172,12 @@
- mode = IVAL(buf,4);
- pid = IVAL(buf,8);
-
- + if ( !Ucrit_checkPid(pid) ) /* added by OH */
- + continue;
- +
- if (IVAL(buf,12) != LOCKING_VERSION || !process_exists(pid)) {
- if (unlink(lname)==0)
- - printf("Deleted stale share file %s\n",s);
- + printf("Deleted stale share file %s\n",s);
- continue;
- }
-
- @@ -194,5 +214,38 @@
- printf("No locked files\n");
-
- return (0);
- +}
- +
- +/* added by OH */
- +void Ucrit_addUsername(pstring username)
- +{
- + strcpy(Ucrit_username, username);
- + if(strlen(Ucrit_username) > 0)
- + Ucrit_IsActive = 1;
- +}
- +
- +unsigned int Ucrit_checkUsername(pstring username)
- +{
- + if ( !Ucrit_IsActive) return 1;
- + if (strcmp(Ucrit_username,username) ==0) return 1;
- + return 0;
- +}
- +
- +void Ucrit_addPid(int pid)
- +{
- + int i;
- + if ( !Ucrit_IsActive) return;
- + for (i=0;i<Ucrit_MaxPid;i++)
- + if( pid == Ucrit_pid[i] ) return;
- + Ucrit_pid[Ucrit_MaxPid++] = pid;
- +}
- +
- +unsigned int Ucrit_checkPid(int pid)
- +{
- + int i;
- + if ( !Ucrit_IsActive) return 1;
- + for (i=0;i<Ucrit_MaxPid;i++)
- + if( pid == Ucrit_pid[i] ) return 1;
- + return 0;
- }
-
- diff -u -r --new-file last-version/source/system.c samba-1.9.15/source/system.c
- --- last-version/source/system.c Thu Sep 21 21:01:05 1995
- +++ samba-1.9.15/source/system.c Mon Nov 13 17:35:06 1995
- @@ -96,7 +96,7 @@
- do {
- if (tval) memcpy((void *)&t2,(void *)tval,sizeof(t2));
- errno = 0;
- - selrtn = select(255,SELECT_CAST fds,NULL,NULL,tval?&t2:NULL);
- + selrtn = select(FD_SETSIZE,SELECT_CAST fds,NULL,NULL,tval?&t2:NULL);
- } while (selrtn<0 && errno == EINTR);
-
- return(selrtn);
- diff -u -r --new-file last-version/source/trans2.c samba-1.9.15/source/trans2.c
- --- last-version/source/trans2.c Sat Nov 11 00:19:11 1995
- +++ samba-1.9.15/source/trans2.c Tue Nov 14 21:58:26 1995
- @@ -300,7 +300,7 @@
-
- strcpy(fname,dname);
-
- - if(mask_match(fname, mask, case_sensitive, False))
- + if(mask_match(fname, mask, case_sensitive, True))
- {
- BOOL isdots = (strequal(fname,"..") || strequal(fname,"."));
- if (dont_descend && !isdots)
- diff -u -r --new-file last-version/source/username.c samba-1.9.15/source/username.c
- --- last-version/source/username.c Sat Sep 2 14:33:27 1995
- +++ samba-1.9.15/source/username.c Mon Nov 13 16:30:59 1995
- @@ -202,19 +202,19 @@
- return(True);
-
- #ifdef NETGROUP
- - if (*p == '@')
- + if (*tok == '@')
- {
- static char *mydomain = NULL;
- if (mydomain == 0)
- yp_get_default_domain(&mydomain);
-
- DEBUG(5,("looking for user %s of domain %s in netgroup %s\n",
- - user, mydomain, p+1));
- + user, mydomain, &tok[1]));
- DEBUG(5,("innetgr is %s\n",
- - innetgr(p + 1, (char *) 0, user, mydomain)
- + innetgr(&tok[1], (char *) 0, user, mydomain)
- ? "TRUE" : "FALSE"));
-
- - if (innetgr(p + 1, (char *)0, user, mydomain))
- + if (innetgr(&tok[1], (char *)0, user, mydomain))
- return (True);
- }
- #endif
- diff -u -r --new-file last-version/source/util.c samba-1.9.15/source/util.c
- --- last-version/source/util.c Sun Nov 12 13:21:27 1995
- +++ samba-1.9.15/source/util.c Tue Nov 14 22:09:36 1995
- @@ -1043,6 +1043,20 @@
- }
-
- /*******************************************************************
- + case insensitive string compararison, length limited
- +********************************************************************/
- +int StrnCaseCmp(char *s, char *t, int n)
- +{
- + while (n-- && *s && *t) {
- + if (tolower(*s) != tolower(*t)) return(tolower(*s) - tolower(*t));
- + s++; t++;
- + }
- + if (n) return(tolower(*s) - tolower(*t));
- +
- + return(0);
- +}
- +
- +/*******************************************************************
- compare 2 strings
- ********************************************************************/
- BOOL strequal(char *s1,char *s2)
- @@ -2831,7 +2845,7 @@
- * simplified regexp that takes * and ? only. Case can be
- * significant or not.
- *********************************************************/
- -BOOL mask_match( char *str, char *regexp, int case_sig, BOOL autoext)
- +BOOL mask_match(char *str, char *regexp, int case_sig, BOOL trans2)
- {
- char *p;
- pstring p1, p2;
- @@ -2860,34 +2874,31 @@
-
- DEBUG(5,("mask_match str=<%s> regexp=<%s>, case_sig = %d\n", p2, p1, case_sig));
-
- - if ((p=strrchr(p1,'.')))
- - {
- + if (trans2) {
- + strcpy(ebase,p1);
- + strcpy(sbase,p2);
- + } else {
- + if ((p=strrchr(p1,'.'))) {
- *p = 0;
- strcpy(ebase,p1);
- strcpy(eext,p+1);
- - }
- - else
- - {
- + } else {
- strcpy(ebase,p1);
- - if (autoext)
- - strcpy(eext,"*");
- - else
- - eext[0] = 0;
- + eext[0] = 0;
- }
-
- - if (!strequal(p2,".") && !strequal(p2,"..") && (p=strrchr(p2,'.')))
- - {
- - *p = 0;
- - strcpy(sbase,p2);
- - strcpy(sext,p+1);
- - }
- - else
- - {
- - strcpy(sbase,p2);
- - strcpy(sext,"");
- - }
- + if (!strequal(p2,".") && !strequal(p2,"..") && (p=strrchr(p2,'.'))) {
- + *p = 0;
- + strcpy(sbase,p2);
- + strcpy(sext,p+1);
- + } else {
- + strcpy(sbase,p2);
- + strcpy(sext,"");
- + }
- + }
-
- - matched = do_match(sbase,ebase,case_sig) && do_match(sext,eext,case_sig);
- + matched = do_match(sbase,ebase,case_sig) &&
- + (trans2 || do_match(sext,eext,case_sig));
-
- DEBUG(5,("mask_match returning %d\n", matched));
-
- @@ -3487,8 +3498,8 @@
- BOOL ip_equal(struct in_addr ip1,struct in_addr ip2)
- {
- unsigned long a1,a2;
- - putip((char *)&a1,(char *)&ip1);
- - putip((char *)&a2,(char *)&ip2);
- + a1 = ntohl(ip1.s_addr);
- + a2 = ntohl(ip2.s_addr);
- return(a1 == a2);
- }
-
- @@ -4042,6 +4053,10 @@
- ****************************************************************************/
- int initgroups(char *name,gid_t id)
- {
- +#ifdef NO_SETGROUPS
- + /* yikes! no SETGROUPS or INITGROUPS? how can this work? */
- + return(0);
- +#else
- gid_t grouplst[NGROUPS_MAX];
- int i,j;
- struct group *g;
- @@ -4068,6 +4083,7 @@
- }
- endgrent();
- return(setgroups(i,grouplst));
- +#endif
- }
- #endif
-
- diff -u -r --new-file last-version/source/version.h samba-1.9.15/source/version.h
- --- last-version/source/version.h Sun Nov 12 21:43:21 1995
- +++ samba-1.9.15/source/version.h Wed Nov 15 00:11:42 1995
- @@ -1 +1 @@
- -#define VERSION "1.9.14p5"
- +#define VERSION "1.9.15"
-